Ich habe einen Befehl, der mehrere Zeilen zurückgibt. Für die weitere Verarbeitung muss ich jede einzelne Zeile dieser Zeilen verarbeiten.
Mein aktueller Code funktioniert durch Ändern des IFS ( Internal Field Separator ):
ROWS=$(some command returning multiple lines)
O=$IFS #save original IFS
IFS=$(echo -en "\n\b") # set IFS to linebreak
for ROW in ${ROWS[@]}
do
echo "$ROW"
done
IFS=$O #restore old IFS
Ich frage mich, gibt es eine bessere Möglichkeit, auf die einzelnen Zeilen der Ausgabe mehrerer Zeilen zuzugreifen, ohne das IFS zu ändern? Insbesondere die Lesbarkeit meines Skripts wird durch das Ändern des IFS beeinträchtigt.
Update: Ich habe Probleme, die Antworten zum Laufen zu bringen, z. B. die von Choroba:
while IFS= read -r line ; do
let var+=line #line 42
done << $(sqlite3 -list -nullvalue NULL -separator ',' /var/log/asterisk/master.db "${QUERY}")
echo "$var" # line 44
gibt mir
./bla.sh: row 44: Warning: here-document at line 43 delimited by end-of-file (wanted `$(sqlite3 -list -nullvalue NULL -separator , /var/log/asterisk/master.db ${QUERY})')
./bla.sh: row 42: let: echo "": syntax error: invalid arithmetic operator. (error causing character is \"""\").
Kann mir jemand dabei helfen? Vielen Dank!
bash
shell
command
command-substitution
stefan.at.wpf
quelle
quelle
< <(some command returning multiple lines)
, aber das ist nicht was du tust.Antworten:
Was ist mit
read
einerwhile
Schleife?Beachten Sie jedoch, dass die Pipe in einer Subshell ausgeführt wird. Dies bedeutet, dass Sie die Variablenwerte für den Rest des Skripts nicht ändern können. Wenn Sie etwas benötigen, um von Ihrer while-Schleife zu überleben, können Sie die Prozessersetzung von bash verwenden:
quelle
bash
Problem. Es ist jedoch anzumerken, dass das Subshell-Scoping von Variablen nur ein Problem darstellt. Wenn Siebash
dasselbe tun,zsh
würde dieses Problem überhaupt nicht auftreten.Es
IFS
reicht nicht aus, nur eine neue Zeile festzulegen. (Warum teilen Sie übrigens auch Rücktaste auf?)In Ihrem Code
${ROWS[@]}
(was eine seltsame Art zu schreiben ist$ROWS
-ROWS
ist kein Array) wird nicht in doppelte Anführungszeichen gesetzt. (Wenn es sich in doppelten Anführungszeichen befindet, erhalten Sie eine einzelne Zeichenfolge, daROWS
es sich nicht um ein Array handelt.) Die Shell teilt den Wert der Variablen bei jedemIFS
Zeichen in Felder auf und behandelt dann jedes Feld als Glob-Muster. Wenn beispielsweise eine der vom Befehl gedruckten Zeilen das einzelne Zeichen enthält*
, wird dieses durch die Dateinamen im aktuellen Verzeichnis ersetzt.Sie können das Globbing mit deaktivieren
set -f
. In den meisten Fällen, in denen Sie dieIFS
Feldaufteilungsfunktion der Shell verwenden möchten, müssen Sie auch das Globbing deaktivieren. Setzen Sie es wieder mitset +f
.Die zuverlässige Redewendung zum zeilenweisen Lesen der Ausgabe eines Befehls lautet
while IFS= read -r
.Beachten Sie, dass die meisten Shells jeden Befehl einer Pipeline in einer separaten Subshell ausführen. Wenn Sie also Variablen festlegen und nach der Schleife verwenden müssen, schließen Sie diese Befehle zusammen mit der Schleife in eine Gruppe ein. (Ksh und zsh sind die Ausnahmen, sie führen den letzten Befehl einer Pipeline in der übergeordneten Shell aus.)
quelle
Sie mischen die Here-Document- und Here-String-Syntax in Ihrer Update-Frage.
Verwenden Sie entweder hier-Dokument:
Oder hier-String:
quelle