linux - rekursiv - Durchsuchen des Inhalts einer Datei in Bash




mehrere dateien nach text durchsuchen linux (8)

Wie wiederhole ich jede Zeile einer Textdatei mit Bash ?

Mit diesem Skript:

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

Ich bekomme 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 komplizierter mit $ p als nur auf dem Bildschirm ausgeben.)

Die Umgebungsvariable SHELL ist (von env):

SHELL=/bin/bash

/bin/bash --version :

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

cat /proc/version versionsausgabe:

Linux version 2.6.18.2-34-default ([email protected]) (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

@Peter: Das könnte für dich funktionieren-

echo "Start!";for p in $(cat ./pep); do
echo $p
done

Dies würde die Ausgabe-

Start!
RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL

Angenommen, 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 von vielen Bash-Lösungen gelesenen Dateiausgabe ändern werden:

  1. Die Leerzeile 4;
  2. Führende oder nachfolgende Leerzeichen in zwei Zeilen;
  3. Die Bedeutung einzelner Zeilen beibehalten (dh jede Zeile ist eine Aufzeichnung);
  4. Die Linie 6 wurde nicht mit einem CR abgeschlossen.

Wenn Sie die Textdatei zeilenweise einschließlich Leerzeilen und Abschlusszeilen ohne CR möchten, müssen Sie eine While-Schleife verwenden und Sie müssen einen alternativen Test für die letzte Zeile haben.

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

1) Verliere die letzte Zeile und führende und nachfolgende 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 -rp; do printf "%s\n" "'$p'"; done </tmp/test.txt , while IFS= read -rp; do printf "%s\n" "'$p'"; done </tmp/test.txt Sie die führenden und nachgestellten Leerzeichen bei, verlieren aber immer noch die letzte Zeile es ist nicht mit CR beendet)

2) Die Verwendung der Prozesssubstitution mit cat wird die gesamte Datei in einem Zug lesen und verliert die Bedeutung einzelner 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 du das " from $(cat /tmp/test.txt) , liest du die Datei Wort für Wort und nicht einen Schluck. Wahrscheinlich auch nicht was $(cat /tmp/test.txt) ist ...)

Die robusteste und einfachste Art, eine Datei Zeile für Zeile zu lesen und alle Abstände zu erhalten, 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 Handelsräume entfernen möchten, entfernen Sie den 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ßendes \n , obwohl ziemlich üblich, wird unter POSIX als fehlerhaft angesehen. Wenn Sie auf das nachgestellte \n zählen können, brauchen Sie || [[ -n $line ]] in der while Schleife nicht.)

Mehr in der BASH FAQ


Ein paar weitere Dinge, die nicht durch andere Antworten abgedeckt sind:

Lesen aus einer Datei mit Trennzeichen

# ':' is the delimiter here, and there are three fields on each line in the file
# IFS set below is restricted to the context of `read`, it doesn't affect any other code
while IFS=: read -r field1 field2 field3; do
  # process the fields
  # if the line has less than three fields, the missing fields will be set to an empty string
  # if the line has more than three fields, `field3` will get all the values, including the third field plus the delimiter(s)
done < input.txt

Lesen von der Ausgabe eines anderen Befehls unter Verwendung der Prozesssubstitution

while read -r line; do
  # process the line
done < <(command ...)

Dieser Ansatz ist besser als command ... | while read -r line; do ... command ... | while read -r line; do ... command ... | while read -r line; do ... weil die while-Schleife hier in der aktuellen Shell statt in einer Subshell wie im Fall der letzteren läuft. Siehe den verwandten Beitrag Eine Variable, die innerhalb einer While-Schleife geändert wurde, wird nicht gespeichert .

Lesen Sie von einer Null-Eingabe, z. B. find ... -print0

while read -r -d '' line; do
  # logic
  # use a second 'read ... <<< "$line"' if we need to tokenize the line
done < <(find /path/to/dir -print0)

Related read: BashFAQ / 020 - Wie kann ich Dateinamen mit Zeilenumbrüchen, Leerzeichen oder beidem finden und sicher verarbeiten?

Lesen von mehr als einer Datei gleichzeitig

while read -u 3 -r line1 && read -u 4 -r line2; do
  # process the lines
  # note that the loop will end when we reach EOF on either of the files, because of the `&&`
done 3< input1.txt 4< input2.txt

Lesen einer ganzen Datei in ein Array (Bash-Versionen früher bis 4)

while read -r line; do
    my_array+=("$line")
done < my_file

Wenn die Datei mit einer unvollständigen Zeile endet (am Ende fehlt eine neue Zeile), dann:

while read -r line || [[ $line ]]; do
    my_array+=("$line")
done < my_file

Lesen einer ganzen Datei in ein Array (Bash-Versionen 4x und höher)

readarray -t my_array < my_file

oder

mapfile -t my_array < my_file

Und dann

for line in "${my_array[@]}"; do
  # process the lines
done

Zusammenhängende Posts:


Eine Möglichkeit, es zu tun ist:

while read p; do
  echo $p
done <peptides.txt

Wenn der Schleifenkörper aus der Standardeingabe lesen kann , können Sie die Datei ausnahmsweise mit einem anderen Dateideskriptor öffnen:

while read -u 10 p; do
  ...
done 10<peptides.txt

Hier ist 10 nur eine willkürliche Zahl (anders als 0, 1, 2).



Wenn Sie nicht möchten, dass Ihr Lesevorgang durch einen Zeilenumbruch 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.


#!/bin/bash
#
# Change the file name from "test" to desired input file 
# (The comments in bash are prefixed with #'s)
for x in $(cat test.txt)
do
    echo $x
done

cat peptides.txt | while read line
do
   # do something with $line here
done






io