Wie iteriert man richtig über Zeilen in Bash, entweder in einer Variablen oder aus der Ausgabe eines Befehls? Das einfache Setzen der IFS-Variablen auf eine neue Zeile funktioniert für die Ausgabe eines Befehls, nicht jedoch beim Verarbeiten einer Variablen, die neue Zeilen enthält.
Zum Beispiel
#!/bin/bash
list="One\ntwo\nthree\nfour"
#Print the list with echo
echo -e "echo: \n$list"
#Set the field separator to new line
IFS=$'\n'
#Try to iterate over each line
echo "For loop:"
for item in $list
do
echo "Item: $item"
done
#Output the variable to a file
echo -e $list > list.txt
#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
echo "Item: $item"
done
Dies ergibt die Ausgabe:
echo:
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four
Wie Sie sehen können, werden beim Echo der Variablen oder beim Iterieren über den cat
Befehl die einzelnen Zeilen korrekt gedruckt. Die erste for-Schleife druckt jedoch alle Elemente in einer einzelnen Zeile. Irgendwelche Ideen?
Antworten:
Wenn Sie mit bash Zeilenumbrüche in eine Zeichenfolge einbetten möchten, schließen Sie die Zeichenfolge ein mit
$''
:Und wenn Sie eine solche Zeichenfolge bereits in einer Variablen haben, können Sie sie zeilenweise lesen mit:
quelle
done <<< "$list"
entscheidend istdone <<< "$list"
dafür ist, dass "$ list" als Eingabe anread
$list
ist sehr wichtig.echo "$list" | while ...
könnte klarer erscheinen als... done <<< "$line"
Sie können
while
+ verwendenread
:Btw. Die
-e
Option zuecho
ist nicht standard. Verwenden Sieprintf
stattdessen, wenn Sie Portabilität wünschen.quelle
<<<
funktioniert die von Glenn Jackman vorgeschlagene Version mit variabler Zuweisung.while
Teil ausführt . Die<<<
Version funktioniert nicht (zumindest in neuen Bash-Versionen).quelle
IFS=$'\n'
für den gleichen Effekt verwenden.Hier ist eine lustige Methode, um Ihre for-Schleife zu erstellen:
Ein wenig sinnvoller / lesbarer wäre:
Aber das ist alles zu komplex, Sie brauchen nur einen Platz darin:
Sie
$line
Variable enthält keine Zeilenumbrüche. Es enthält Instanzen von\
gefolgt vonn
. Das können Sie deutlich sehen mit:Die Ersetzung ersetzt diese durch Leerzeichen, was ausreicht, um for-Schleifen zu bearbeiten:
Demo:
quelle
cr
Sie verwenden können , anstatt sie zu definieren$'\n'
.Sie können die Variable auch zuerst in ein Array konvertieren und dann darüber iterieren.
Dies ist nur dann nützlich, wenn Sie sich nicht
IFS
mit demread
befehl anlegen möchten und auch Probleme mit dem befehl haben, da es passieren kann, dass Sie ein anderes Skript in der Schleife aufrufen, das Ihren Lesepuffer vor der Rückkehr leeren kann, wie es mir passiert ist .quelle