web-dev-qa-db-fra.com

Comment utiliser la commande de lecture dans Bash?

Lorsque j'essaie d'utiliser la commande read dans Bash, procédez comme suit:

echo hello | read str
echo $str

Rien ne fait écho, alors que je pense que str devrait contenir la chaîne hello. Quelqu'un peut-il m'aider à comprendre ce comportement?

49
Determinant

La read dans votre commande de script convient. Cependant, vous l'exécutez dans le pipeline, ce qui signifie qu'il se trouve dans un sous-shell. Par conséquent, les variables lues ne sont pas visibles dans le Shell parent. Tu peux soit

  • déplacez également le reste du script dans le sous-shell:

    echo hello | { read str
      echo $str
    }
    
  • ou utilisez la substitution de commande pour obtenir la valeur de la variable du sous-shell

    str=$(echo hello)
    echo $str
    

    ou un exemple un peu plus compliqué (Saisir le 2ème élément de ls)

    str=$(ls | { read a; read a; echo $a; })
    echo $str
    
54
jpalecek

Autres alternatives bash n'impliquant pas de sous-shell:

read str <<END             # here-doc
hello
END

read str <<< "hello"       # here-string

read str < <(echo hello)   # process substitution
36
glenn jackman

L'utilisation typique pourrait ressembler à:

i=0
echo -e "hello1\nhello2\nhello3" | while read str ; do
    echo "$((++i)): $str"
done

et sortie

1: hello1
2: hello2
3: hello3
8
Shizzmo

La valeur disparaît puisque la commande de lecture est exécutée dans un sous-shell distinct: Bash FAQ 24

3
l0b0

Pour mettre mes deux cents ici: sur KSH, reading en tant que tel à une variable [ fonctionnera, car selon la documentation IBM AIX , la variable readdo de KSH affecte l'environnement Shell actuel:

La définition des variables du shell par la commande de lecture affecte l'environnement d'exécution du shell en cours.

Cela m’a simplement pris quelques bonnes minutes à comprendre pourquoi un one-liner se terminant par read que j’avais utilisé zillion fois auparavant sous AIX ne fonctionnait pas sous Linux ... c’est parce que KSH enregistre dans l’environnement actuel et BASH non!

2
RAKK

Je n'utilise vraiment que lire avec "while" et une boucle do: 

echo "This is NOT a test." | while read -r a b c theRest; do  
echo "$a" "$b" "$theRest"; done  

C'est un test.
Pour ce que ça vaut, j’ai vu la recommandation de toujours utiliser -r avec la commande read de bash. 

0
JackDR