problème readarray (ou pipe)

Je suis coincé avec un comportement étrange de la commande readarray.

Le man bash indique:

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 ceux-ci fonctionnent:

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 est le problème avec le tuyau?

Réponse

Peut-être essayer:

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

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

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

… doesn « t – la valeur de la variable a été définie dans un différent processus shell que celui dans lequel vous lappelez.

Réponse

Pour vous assurer que sexécute dans le shell actuel, soit utilisez la substitution de processus à la place du pipeline:

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

ou (si bash 4.2 ou version ultérieure) utilisez loption shell lastpipe:

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

Commentaires

  • Cool. Cela fonctionne, mais quest-ce que la substitution de processus? Et que signifie avoir < < 2 flèches?
  • Consultez la page de manuel bash. En bref, cest la syntaxe ' pour traiter un pipeline comme un descripteur de fichier. < <(...) signifie rediriger lentrée (le premier <) de la sortie de la commande à lintérieur de <(...). De même, > >(...) transmettrait la sortie standard à lentrée standard du pipeline à lintérieur de >(...). Vous navez ' pas nécessairement besoin dutiliser la redirection avec substitution de processus. cat <( echo a b c ) fonctionne également.
  • 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 na pas ce problème.
  • Les fins de ligne peuvent être supprimées en utilisant readarray -t arr. Depuis man bash: -t Remove a trailing newline from each line read.
  • I ' m en utilisant bash 5.0.17 et cela ne fonctionne pas ' pour moi. Jai ' même vérifié BASHOPTS et il contient lastpipe, encore cat myfile.txt | readarray -t arr donne un arr vide, mais readarray -t arr < <(cat myfile.txt) fonctionne correctement.

Answer

readarray peut également lire depuis stdin, donc:

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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *