Ich habe mich an ein seltsames Verhalten des Befehls readarray gehalten.
In man bash heißt es:
readarray Read lines from the standard input into the indexed array variable array
, aber diese Skripte funktionieren nicht (Array ist leer):
unset arr; (echo a; echo b; echo c) | readarray arr; echo ${#arr[@]} unset arr; cat /etc/passwd | readarray arr; echo ${#arr[@]}
Und diese funktionieren:
unset arr; readarray arr < /etc/passwd ; echo ${#arr[@]} unset arr; mkfifo /tmp/fifo; (echo a; echo b; echo c) > /tmp/fifo & mapfile arr < /tmp/fifo ; echo ${#arr[@]}
Was ist mit der Pipe falsch?
Antwort
Vielleicht versuchen Sie:
unset arr printf %s\\n a b c | { readarray arr echo ${#arr[@]} }
Ich gehe davon aus, dass es funktionieren wird , aber in dem Moment, in dem Sie aus dieser letzten { Shell ; } -Kontext am Ende des | Pipeline dort verlieren Sie Ihren Variablenwert. Dies liegt daran, dass jeder der | separaten | -Prozesse innerhalb einer | -Pipeline in ausgeführt wird eine ( Subshell ). Ihr Ding funktioniert also aus demselben Grund nicht:
( arr=( a b c ) ) ; echo ${arr[@]}
… funktioniert nicht – der Variablenwert wurde in einem anderen
Antwort
Um sicherzustellen, dass wird in der aktuellen Shell ausgeführt. Verwenden Sie entweder die Prozessersetzung anstelle der Pipeline:
readarray -t arr < <( echo a; echo b; echo c )
oder (wenn bash 4.2 oder höher) Verwenden Sie die Shell-Option lastpipe:
shopt -s lastpipe ( echo a; echo b; echo c ) | readarray -t arr
Kommentare
- Cool. Das funktioniert, aber was genau ist Prozesssubstitution? Und was bedeutet es,
< <2 Pfeile zu haben? - Siehe die Manpage
bash. Kurz gesagt, es ist die Syntax von ' zum Behandeln einer Pipeline als Dateideskriptor.< <(...)bedeutet, dass Eingaben (die erste<) von der Ausgabe des Befehls innerhalb von<(...). Ähnlich würde> >(...)die Standardausgabe an die Standardeingabe der Pipeline innerhalb von>(...)übergeben. ' muss nicht unbedingt die Umleitung mit Prozessersetzung verwenden.cat <( echo a b c )funktioniert auch. - Diese beiden Optionen führen für mich zu einem unerwünschten Ergebnis, bei dem jedes Array-Element die Zeilenenden am Ende jeder Zeichenfolge beibehält. Während die Antwort von smac89 dieses Problem nicht hat.
- Zeilenenden können mit
readarray -t arrentfernt werden. Vonman bash:-t Remove a trailing newline from each line read. - Ich ' m benutze
bash5.0.17 und dies funktioniert bei mir nicht '. Ich ' habe sogarBASHOPTSüberprüft und es enthältlastpipe, abercat myfile.txt | readarray -t arrgibt ein leeresarraus, aberreadarray -t arr < <(cat myfile.txt)funktioniert ordnungsgemäß.
Antwort
readarray kann auch von stdin lesen, also:
readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}