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?

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.


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

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[@]}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.