Readarray (oder Pipe) Problem


19

Ich blieb bei einem merkwürdigen readarrayKommandoverhalten.

Die man bashStaaten:

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 Arbeit:

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 los mit Pipe?

Antworten:


15

Vielleicht versuchen Sie:

unset arr
printf %s\\n a b c | {
    readarray arr
    echo ${#arr[@]}
}

Ich gehe davon aus, dass es funktionieren wird, aber sobald Sie den letzten {Shell- ; }Kontext am Ende der |Pipeline verlassen, verlieren Sie Ihren Variablenwert. Dies liegt daran, dass jeder der |separaten |Prozesse in einer |Pipeline in einer (Subshell ausgeführt wird ). Dein Ding funktioniert also nicht aus dem gleichen Grund:

( arr=( a b c ) ) ; echo ${arr[@]}

... nicht - der Variablenwert wurde in einem anderen Shell-Prozess als dem festgelegt, in dem Sie ihn aufrufen.


23

readarrayVerwenden Sie entweder die Prozessersetzung anstelle der Pipeline, um sicherzustellen, dass der Befehl in der aktuellen Shell ausgeführt wird:

readarray arr < <( echo a; echo b; echo c )

oder (wenn bash4.2 oder neuer) benutze die lastpipeShell Option:

shopt -s lastpipe
( echo a; echo b; echo c ) | readarray arr

1
Cool. Das funktioniert, aber was genau ist Prozesssubstitution? Und was bedeutet es, < <2 Pfeile zu haben ?
CMCDragonkai

1
Siehe die bashManpage. Kurz gesagt, es handelt sich um eine Syntax zur Behandlung einer Pipeline als Dateideskriptor. < <(...)bedeutet, die Eingabe (die erste <) von der Ausgabe des Befehls nach innen umzuleiten <(...). In ähnlicher Weise > >(...)würde die Standardausgabe an die Standardeingabe der internen Pipeline übergeben >(...). Sie müssen die Umleitung nicht unbedingt für die Prozessersetzung verwenden. cat <( echo a b c )funktioniert auch.
Chepner

Beide 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.
Thnee

3

readarray kann auch von stdin lesen, also:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.