Bash Read: Durch Kommas getrennte Liste lesen, letztes Element fehlt

8

Die Ausgabe des folgenden Befehls ist für mich seltsam. Warum gibt es mir Element 5 nicht zurück?

$ echo '0,1,2,3,4,5' | while read -d, i; do echo $i; done
0
1
2
3
4

Ich würde erwarten, dass '5' ebenfalls zurückgegeben wird. Laufen GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu). Das Hinzufügen eines Kommas funktioniert, aber meine Eingabedaten haben kein Komma. Vermisse ich etwas

Karlo
quelle

Antworten:

12

Mit read, -dwird verwendet , um zu beenden die Eingangsleitungen (dh nicht an getrennten Eingangsleitungen). Ihre letzte "Zeile" enthält keinen Terminator, readgibt also bei EOF false zurück und die Schleife wird beendet (obwohl der endgültige Wert gelesen wurde).

echo '0,1,2,3,4,5' | { while read -d, i; do echo "$i"; done; echo "last value=$i"; }

(Auch bei -d, readauch verwendet $IFS, einschließlich der Leer Absorbieren nachlauf \nauf dem letzten Wert, der unter Verwendung anderer Methoden wie erscheinen würde readarray)

In den Bash-FAQ wird dies und die Behandlung verschiedener ähnlicher Fälle erläutert:

mr.spuratic
quelle
8
Ich denke man könnte read -d, i || [[ -n $i ]]a la machen Was bedeutet while read -r line || [[ -n $line ]]das?
Steeldriver
8

Wie in anderen Antworten angegeben, -dhandelt es sich um ein Zeilenendezeichen und nicht um ein Feldtrennzeichen. Du kannst tun

IFS=, read -a fields <<< "1,2,3,4,5"
for i in "${fields[@]}"; do echo "$i"; done
Graham Breed
quelle
5

Vom Menschen:

-d delim

Das erste Zeichen von delim wird verwendet, um die Eingabezeile und nicht die neue Zeile zu beenden.

Ihr Element 5 hat kein Trennzeichen (Komma), daher wird es nicht gelesen.

Siva
quelle
Die beste Lösung ist also, nach der Eingabe ein weiteres Komma zu setzen?
Karlo
3
Die beste Lösung könnte darin bestehen, Daten mit etwas anderem als einer Shell zu verarbeiten . Da die Antwortenden hier die aktuelle Frage beantwortet haben, können Sie eine separate Frage in Betracht ziehen, die Ihr größeres Ziel demonstriert.
Jeff Schaller
3

Was Sie sehen, ist dasselbe Verhalten (und aus demselben Grund) wie Warum erkennt diese 'while'-Schleife die letzte Zeile nicht?

Wie in diesem Fall können Sie das Verhalten wie folgt ändern, indem Sie der Schleifenbeendigungsbedingung einen zusätzlichen Test hinzufügen

while read -d, i || [[ -n $i ]]; do ...

Ex.

$ echo '0,1,2,3,4,5' | while read -d, i || [[ -n $i ]]; do echo $i; done
0
1
2
3
4
5
Steeldriver
quelle