problème de lecture (ou de canal)

19

Je suis resté avec un étrange comportement de readarraycommandement.

Les man bashétats:

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

mais ces scripts ne fonctionnent pas (le tableau est vide):

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

Et ces travaux:

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

Quel mal avec la pipe?

dchirikov
la source

Réponses:

15

Essayez peut-être:

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

Je m'attends à ce que cela fonctionne, mais au moment où vous sortez de ce dernier contexte de {shell ; }à la fin du |pipeline, vous perdrez votre valeur de variable. En effet, chacun des processus |distincts d' |un |pipeline est exécuté dans un (sous - shell ). Donc votre truc ne marche pas pour la même raison:

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

... ne fait pas - la valeur de la variable a été définie dans un processus shell différent de celui dans lequel vous l'appelez.

mikeserv
la source
23

Pour vous assurer que la readarraycommande s'exécute dans le shell actuel, utilisez la substitution de processus à la place du pipeline:

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

ou (si bash4.2 ou version ultérieure) utilisez l' lastpipeoption shell:

shopt -s lastpipe
( echo a; echo b; echo c ) | readarray arr
chepner
la source
1
Cool. Cela fonctionne, mais quelle est exactement la substitution de processus? Et que signifie avoir < <2 flèches?
CMCDragonkai
1
Voir la bashpage de manuel. En bref, c'est la syntaxe pour traiter un pipeline comme un descripteur de fichier. < <(...)signifie rediriger l'entrée (la première <) de la sortie de la commande à l'intérieur <(...). De même, > >(...)passerait la sortie standard à l'entrée standard du pipeline à l'intérieur >(...). Vous n'avez pas nécessairement besoin d'utiliser la redirection avec la substitution de processus. cat <( echo a b c )fonctionne aussi bien.
chepner
Ces deux options produisent un résultat indésirable pour moi, où chaque élément du tableau conserve les fins de ligne à la fin de chaque chaîne. Alors que la réponse de smac89 n'a pas ce problème.
thnee
3

readarray peut également lire depuis stdin, donc:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]}
smac89
la source