problema readarray (o pipe)


19

Mi sono bloccato con uno strano comportamento di readarraycomando.

Gli man bashstati:

readarray
     Read lines from the standard input into the indexed array variable array

ma questi script non funzionano (l'array è vuoto):

unset arr; (echo a; echo b; echo c) | readarray arr; echo ${#arr[@]}
unset arr; cat /etc/passwd | readarray arr;  echo ${#arr[@]}

E questi funzionano:

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[@]}

Cosa c'è che non va nella pipa?

Risposte:


15

Forse prova:

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

Mi aspetto che funzioni, ma nel momento in cui esci dall'ultimo contesto della {shell ; }alla fine della |pipeline, perderai il valore della variabile. Questo perché ciascuno dei processi |separati |all'interno di una |pipeline viene eseguito in una (subshell ). Quindi la tua cosa non funziona per lo stesso motivo:

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

... no: il valore della variabile è stato impostato in un processo shell diverso da quello in cui lo si chiama.


23

Per assicurarsi che il readarraycomando venga eseguito nella shell corrente, utilizzare la sostituzione del processo al posto della pipeline:

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

o (se bash4.2 o successivo) usa l' lastpipeopzione shell:

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

1
Freddo. Funziona, ma cos'è esattamente la sostituzione di processo? E cosa significa avere < <2 frecce?
CMCDragonkai,

1
Vedi la bashpagina man. In breve, è una sintassi per trattare una pipeline come un descrittore di file. < <(...)significa reindirizzare l'input (il primo <) dall'output del comando all'interno <(...). Allo stesso modo, > >(...)passerebbe l'output standard all'input standard della pipeline all'interno >(...). Non è necessario utilizzare necessariamente il reindirizzamento con la sostituzione del processo. cat <( echo a b c )funziona pure.
Chepner,

Entrambe queste opzioni producono un risultato indesiderato per me, in cui ogni elemento dell'array mantiene le terminazioni di riga alla fine di ogni stringa. Considerando che la risposta di smac89 non ha questo problema.
giovedì

3

readarray può anche leggere da stdin, quindi:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.