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 arr
entfernt werden. Vonman bash
:-t Remove a trailing newline from each line read.
- Ich ' m benutze
bash
5.0.17 und dies funktioniert bei mir nicht '. Ich ' habe sogarBASHOPTS
überprüft und es enthältlastpipe
, abercat myfile.txt | readarray -t arr
gibt ein leeresarr
aus, 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[@]}