Sono rimasto bloccato con uno strano comportamento del comando readarray
.
Il man bash
afferma:
readarray Read lines from the standard input into the indexed array variable array
ma questi script non funzionano (larray è 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è di sbagliato in pipe?
Risposta
Forse prova:
unset arr printf %s\\n a b c | { readarray arr echo ${#arr[@]} }
Mi aspetto che funzioni , ma nel momento in cui esci dallultimo contesto {
shell ; }
alla fine del |
pipeline lì perderai il valore della variabile. Questo perché ciascuno dei |
|
processi separati allinterno di una |
pipeline viene eseguito in una (
subshell )
. Quindi la tua cosa non funziona per lo stesso motivo:
( arr=( a b c ) ) ; echo ${arr[@]}
… non “t – il valore della variabile è stato impostato in un diverso processo della shell rispetto a quello in cui lo chiami.
Rispondi
Per assicurarti che readarray
il comando viene eseguito nella shell corrente, o utilizza la sostituzione del processo al posto della pipeline:
readarray -t arr < <( echo a; echo b; echo c )
o (se bash
4.2 o versione successiva) utilizza lastpipe
opzione della shell:
shopt -s lastpipe ( echo a; echo b; echo c ) | readarray -t arr
Commenti
Risposta
readarray
può leggere anche da stdin, quindi:
readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
< <
2 frecce?bash
. In breve, è ' la sintassi per trattare una pipeline come un descrittore di file.< <(...)
significa reindirizzare linput (il primo<
) dalloutput del comando allinterno di<(...)
. Allo stesso modo,> >(...)
passerebbe lo standard output allo standard input della pipeline allinterno di>(...)
. Non è necessario ' utilizzare il reindirizzamento con sostituzione del processo. Anchecat <( echo a b c )
funziona.readarray -t arr
. Daman bash
:-t Remove a trailing newline from each line read.
bash
5.0.17 e questo ' non funziona per me. ' ho anche controllatoBASHOPTS
e contienelastpipe
, macat myfile.txt | readarray -t arr
restituisce unarr
, mareadarray -t arr < <(cat myfile.txt)
funziona correttamente.