Was erklärt werden muss, ist, dass der Befehl zu funktionieren schien, nicht sein Exit-Code
'\n'
besteht aus zwei Zeichen: einem Backslash \und einem Buchstaben n. Was Sie für nötig hielten, war $'\n'
ein Zeilenvorschub (aber das wäre auch nicht richtig, siehe unten).
Die -d
Option macht dies:
-d delim continue until the first character of DELIM is read, rather
than newline
Ohne diese Option read
würde ich also bis zu einer neuen Zeile lesen, die Zeile in Wörter aufteilen, wobei die Zeichen $IFS
als Trennzeichen verwendet werden, und die Wörter in das Array einfügen . Wenn Sie angeben -d $'\n'
, dass das Zeilentrennzeichen auf eine neue Zeile gesetzt wird, würde es genau dasselbe tun . Einstellung -d '\n'
bedeutet, dass bis zum ersten Backslash gelesen wird (siehe jedoch unten), bei dem es sich um das erste Zeichen in handelt delim
. Da Ihre Datei keinen Backslash enthält, read
wird der am Ende der Datei beendet und:
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.
Deshalb ist der Exit-Code 1.
Aus der Tatsache, dass Sie glauben, dass der Befehl funktioniert hat, können wir schließen, dass die Datei keine Leerzeichen enthält, sodass sie read
nach dem Lesen der gesamten Datei in der vergeblichen Hoffnung, einen Backslash zu finden, durch Leerzeichen (den Standardwert von) aufgeteilt wird $IFS
), einschließlich Zeilenumbrüche. Daher wird jede Zeile (oder jedes Wort, wenn eine Zeile mehr als ein Wort enthält) im Array gespeichert.
Der mysteriöse Fall des entwendeten Rückschlags
Woher wusste ich, dass die Datei keine Backslashes enthält? Weil Sie die -r
Flagge nicht geliefert haben an read
:
-r do not allow backslashes to escape any characters
Wenn Sie also Backslashes in der Datei gehabt hätten, wären diese entfernt worden, es sei denn, Sie hätten zwei davon hintereinander. Und natürlich gibt es Beweise, read
die einen Exit-Code von 1 hatten, was zeigt, dass kein Backslash gefunden wurde, also gab es auch nicht zwei hintereinander.
Imbissbuden
Bash wäre keine Bash, wenn sich nicht hinter fast jedem Befehl Fallstricke verstecken würden, und das read
ist keine Ausnahme. Hier sind ein paar:
Sofern Sie nichts anderes angeben -r
, read
werden Backslash-Escape-Sequenzen interpretiert. Sofern dies nicht tatsächlich das ist, was Sie möchten (was gelegentlich, aber nur gelegentlich -r
der Fall ist ), sollten Sie dies angeben , um zu vermeiden, dass Zeichen in dem seltenen Fall verschwinden, dass die Eingabe Backslashes enthält.
Die Tatsache, dass read
ein Exit-Code von 1 zurückgegeben wird, bedeutet nicht, dass er fehlgeschlagen ist. Es könnte durchaus gelungen sein, außer den Leitungsabschluss zu finden. Seien Sie also vorsichtig mit einer Schleife wie folgt aus : while read -r LINE; do something with LINE; done
weil es zum Scheitern verurteilt wird do something
mit der letzten Zeile in dem seltenen Fall , dass die letzte Zeile nicht eine neue Zeile am Ende hat.
read -r LINE
Bewahrt Backslashes, aber keine führenden oder nachfolgenden Leerzeichen.
while read
" zu empfehlen . Ansonsten fantastische Antwort.while read
, solange Sie nichts in der Schleife haben. Ansonsten ist es ein Käfer, der darauf wartet, dich zu beißen - und glaub mir, ich bin gebissen worden.read
.mapfile
ist ziemlich cool. Für einen schnellen und schmutzigen Hack verwende ich die verbotene while-Schleife, aber ich habe aufgehört, sie in Produktionsskripte einzufügen. YMMV und ich haben die Warnung in der Antwort gemildert.Das ist das erwartete Verhalten:
quelle