2121 Stimmen

Schleifenbildung durch den Inhalt einer Datei in der Bash

Wie kann ich durch jede Zeile einer Textdatei iterieren mit Bash ?

Mit diesem Skript:

echo "Start!"
for p in (peptides.txt)
do
    echo "${p}"
done

Ich erhalte diese Ausgabe auf dem Bildschirm:

Start!
./runPep.sh: line 3: syntax error near unexpected token `('
./runPep.sh: line 3: `for p in (peptides.txt)'

(Später möchte ich etwas Komplizierteres machen mit $p als nur die Ausgabe auf dem Bildschirm).


Die Umgebungsvariable SHELL ist (von env):

SHELL=/bin/bash

/bin/bash --version Ausgabe:

GNU bash, version 3.1.17(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

cat /proc/version Ausgabe:

Linux version 2.6.18.2-34-default (geeko@buildhost) (gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)) #1 SMP Mon Nov 27 11:46:27 UTC 2006

Die Datei peptides.txt enthält:

RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL

54voto

Jahid Punkte 19666

Verwenden Sie eine while-Schleife, etwa so:

while IFS= read -r line; do
   echo "$line"
done <file

Anmerkungen:

  1. Wenn Sie nicht die IFS ordnungsgemäß, verlieren Sie die Einrückung.

  2. Sie sollten fast immer die Option -r bei read verwenden.

  3. Lesen Sie keine Zeilen mit for

19voto

Anjul Sharma Punkte 169

Wenn Sie nicht wollen, dass Ihr Lesevorgang durch ein Zeilenumbruchzeichen unterbrochen wird, verwenden Sie -

#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
    echo "$line"
done < "$1"

Führen Sie dann das Skript mit dem Dateinamen als Parameter aus.

17voto

dawg Punkte 89931

Nehmen wir an, Sie haben diese Datei:

$ cat /tmp/test.txt
Line 1
    Line 2 has leading space
Line 3 followed by blank line

Line 5 (follows a blank line) and has trailing space    
Line 6 has no ending CR

Es gibt vier Elemente, die die Bedeutung der Dateiausgabe, die von vielen Bash-Lösungen gelesen wird, verändern:

  1. Die leere Zeile 4;
  2. Führende oder nachgestellte Leerzeichen in zwei Zeilen;
  3. Beibehaltung der Bedeutung der einzelnen Zeilen (d.h. jede Zeile ist ein Datensatz);
  4. Die Zeile 6 wurde nicht mit einem CR abgeschlossen.

Wenn Sie die Textdatei zeilenweise mit Leerzeilen und abschließenden Zeilen ohne CR abfragen wollen, müssen Sie eine while-Schleife verwenden und einen alternativen Test für die letzte Zeile vorsehen.

Hier sind die Methoden, die die Datei verändern können (im Vergleich zu dem, was cat zurück):

1) Streichen Sie die letzte Zeile und die führenden und nachfolgenden Leerzeichen:

$ while read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'

(Wenn Sie while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt stattdessen bleiben die vor- und nachgestellten Leerzeichen erhalten, aber die letzte Zeile geht verloren, wenn sie nicht mit CR abgeschlossen wird)

2) Verwendung der Prozess-Substitution mit cat liest die gesamte Datei in einem Zug und verliert die Bedeutung der einzelnen Zeilen:

$ for p in "$(cat /tmp/test.txt)"; do printf "%s\n" "'$p'"; done
'Line 1
    Line 2 has leading space
Line 3 followed by blank line

Line 5 (follows a blank line) and has trailing space    
Line 6 has no ending CR'

(Wenn Sie die " von $(cat /tmp/test.txt) Sie lesen die Datei Wort für Wort und nicht in einem Zug. Wahrscheinlich auch nicht das, was beabsichtigt ist...)


Die robusteste und einfachste Methode, eine Datei zeilenweise zu lesen und alle Abstände beizubehalten, ist:

$ while IFS= read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
'    Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space    '
'Line 6 has no ending CR'

Wenn Sie führende und handelnde Leerzeichen entfernen möchten, entfernen Sie die IFS= Teil:

$ while read -r line || [[ -n $line ]]; do printf "'%s'\n" "$line"; done </tmp/test.txt
'Line 1'
'Line 2 has leading space'
'Line 3 followed by blank line'
''
'Line 5 (follows a blank line) and has trailing space'
'Line 6 has no ending CR'

(Eine Textdatei ohne abschließende \n ist zwar weit verbreitet, gilt aber unter POSIX als fehlerhaft. Wenn Sie sich auf die nachgestellten \n brauchen Sie nicht || [[ -n $line ]] im while Schleife.)

Mehr auf der BASH-FAQ

13voto

xekon Punkte 407

Das ist vielleicht die einfachste Lösung, und vielleicht funktioniert sie nicht in allen Fällen, aber für mich funktioniert sie hervorragend:

while read line;do echo "$line";done<peptides.txt

wenn Sie Leerzeichen in Klammern einschließen müssen:

while read line;do echo \"$line\";done<peptides.txt

Ahhh, das ist so ziemlich das Gleiche wie die Antwort, die am meisten hochgestimmt wurde, aber alles in einer Zeile.

12voto

hamou92 Punkte 512

Ich verwende gerne xargs anstelle von while . xargs ist leistungsstark und kommandozeilenfreundlich

cat peptides.txt | xargs -I % sh -c "echo %"

Mit xargs können Sie auch die Ausführlichkeit mit -t und Validierung mit -p

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X