2013-10-24 4 views
46

Bash verwenden können: cat <(echo "$FILECONTENT")Wie Eingang Rohr zu einer Bash while-Schleife und bewahren Variablen nach Schleife endet

Bash lassen auch verwenden: while read i; do echo $i; done </etc/passwd

zu kombinieren vorherigen zwei dieser verwendet werden können: echo $FILECONTENT | while read i; do echo $i; done

Das Problem mit der letzten ist, dass es Sub-Shell erstellt und nach der While-Schleife endet die Variable i kann nicht mehr zugegriffen werden.

Meine Frage ist:

Wie so etwas zu erreichen: while read i; do echo $i; done <(echo "$FILECONTENT") oder mit anderen Worten: Wie kann ich die i überleben while-Schleife sicher sein?

Bitte beachten Sie, dass ich während Aussage bewusst bin in {} einschließe aber das löst nicht das Problem (man stelle sich, dass Sie die while-Schleife in der Funktion verwendet werden soll und das Rück i Variable)

+0

http://mywiki.wooledge.org/BashFAQ/024 – tripleee

+0

In Verbindung stehend: https://stackoverflow.com/questions/37229058/append-to-an-array-variable-from-a-pipeline-command. Erläutert alle Optionen einschließlich der unten genannten Prozessvertretung und 'lastpipe' und deren Vor- und Nachteile. –

+0

Related: [Eine Variable innerhalb einer While-Schleife geändert wird nicht erinnert] (https://stackoverflow.com/questions/16854280/a-variable-modified-inside-a-while-loop-is-not-remembered). – codeforester

Antwort

60

Die korrekte Schreibweise für Process Substitution ist:

while read i; do echo $i; done < <(echo "$FILECONTENT") 

der letzte Wert von i in der Schleife zugeordnet ist dann verfügbar, wenn die Schleife beendet. Eine Alternative ist:

echo $FILECONTENT | 
{ 
while read i; do echo $i; done 
...do other things using $i here... 
} 

Die Streben sind eine I/O-Gruppierung Betrieb und nicht selbst eine Subshell erstellen. In diesem Zusammenhang sind sie Teil einer Pipeline und werden daher als Subshell ausgeführt, aber es ist wegen der |, nicht der { ... }. Sie erwähnen das in der Frage. AFAIK, können Sie eine Rückkehr von innerhalb dieser innerhalb einer Funktion tun.


Bash bietet auch die shopt builtin und einer seiner vielen Optionen ist:

lastpipe

Wenn gesetzt, und Auftragssteuerung ist nicht aktiv, die Shell den letzten Befehl eines läuft Pipeline wird nicht im Hintergrund in der aktuellen Shell-Umgebung ausgeführt.

So wie dies mit etwas in einem Skript macht die modfied sum zur Verfügung, nachdem die Schleife:

FILECONTENT="12 Name 
13 Number 
14 Information" 
shopt -s lastpipe # Comment this out to see the alternative behaviour 
sum=0 
echo "$FILECONTENT" | 
while read number name; do ((sum+=$number)); done 
echo $sum 

dies an der Linie in der Regel Befehl Doing läuft Foul von ‚Auftragssteuerung ist nicht aktiv‘ (Das heißt, in der Befehlszeile ist die Jobsteuerung aktiv). Das Testen ohne Verwendung eines Skripts ist fehlgeschlagen.

auch, wie Gareth Rees in seiner answer erwähnt, können Sie manchmal verwenden ein here string:

while read i; do echo $i; done <<< "$FILECONTENT" 

Diese nicht shopt erfordert; Sie können möglicherweise einen Prozess mit diesem speichern.

+0

Verzeihen Sie meine Ignoranz. Ich weiß, das ist die richtige Lösung und ich habe es als Antwort markiert, so dass es für mich funktioniert hat. Aber jetzt, wenn ich 'lese, während ich lese; echo $ i; Fertig <<(Katze/etc/passwd); echo $ i' Es kam nicht zweimal die letzte Zeile zurück. Was mache ich falsch? –

+0

@WakanTanka: Ich musste etwas experimentieren ... Ich glaube, die Antwort ist, dass das fehlgeschlagene Lesen "i" zurücksetzt, so dass das Echo nach der Schleife eine leere Zeile wiedergibt. –

+0

Kudos für die Prozesssubstitution Referenz. Ich wusste es nicht. – Atcold