Edit: Originaltitel lautete "Lesen schlägt in Bash fehl"
Mit ksh verwende ich read, um Werte bequem zu trennen:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
2 1
$
Aber es schlägt fehl in bash:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
$
Ich habe in der Manpage keinen Grund gefunden, warum dies fehlschlägt. Irgendeine Idee?
Antworten:
bash
Führt die rechte Seite einer Pipeline in einem Subshell-Kontext aus , sodass Änderungen an Variablen (was auch immer derread
Fall ist) nicht beibehalten werden. Sie sterben am Ende des Befehls ab, wenn die Subshell dies tut.Stattdessen können Sie die Prozessersetzung verwenden :
In diesem Fall
read
wird in unserer primären Shell ausgeführt, und unser Befehl zur Ausgabeerzeugung wird in der Subshell ausgeführt. Die<(...)
Syntax erstellt eine Subshell und verbindet ihre Ausgabe mit einer Pipe, die wirread
mit der normalen<
Operation in die Eingabe von umleiten . Da esread
in unserer Haupt-Shell lief, sind die Variablen korrekt gesetzt.Wie in einem Kommentar erwähnt, können Sie einen Here-String verwenden , wenn Sie eine Zeichenfolge buchstäblich in Variablen aufteilen möchten :
Ich nehme an, dass es mehr als das gibt, aber dies ist eine bessere Option, wenn es keine gibt.
quelle
read a b dump <<< '1 2 3 4 5'
.cat /etc/passwd | (read -r line ; echo $line)
. Aber der nächste,echo
der$line
nicht in der Pipeline ist, bringt nichts auf den Bildschirm, weil der Wert nur zwischen Klammern (Subshell) existierte. Hoffe, es hilft jemandem.Dies ist kein
bash
Fehler, daPOSIX
beidebash
undksh
Verhaltensweisen zulässig sind, was zu der unglücklichen Diskrepanz führt, die Sie beobachten.http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
Darüber hinaus befindet sich jeder Befehl einer Multi-Command-Pipeline in einer Subshell-Umgebung. Als Erweiterung können jedoch einige oder alle Befehle in einer Pipeline in der aktuellen Umgebung ausgeführt werden. Alle anderen Befehle sollen in der aktuellen Shell-Umgebung ausgeführt werden.
Mit
bash 4.2
und neuer können Sie jedoch dielastpipe
Option in nicht interaktiven Skripten festlegen , um das erwartete Ergebnis zu erhalten, z.Ausgabe:
quelle
lastpipe
ist, dass es in anderen Shells (zB Bindestrich) nicht funktioniert. Grundsätzlich gibt es keine Möglichkeit, dieses tragbare System so