Edit: le titre d'origine était "la lecture échoue dans bash"
Avec ksh, j'utilise read comme moyen pratique de séparer les valeurs:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
2 1
$
Mais cela échoue en bash:
$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a
$
Je n'ai trouvé aucune raison dans la page de manuel pour laquelle il échoue, une idée?
Réponses:
bash
exécute le côté droit d'un pipeline dans un contexte de sous - shell , donc les modifications apportées aux variables (ce qui est leread
cas) ne sont pas conservées - elles meurent lorsque le sous-shell le fait, à la fin de la commande.Au lieu de cela, vous pouvez utiliser la substitution de processus :
Dans ce cas,
read
s'exécute dans notre shell principal et notre commande de production de sortie s'exécute dans le sous-shell. La<(...)
syntaxe crée un sous-shell et connecte sa sortie à un tube, que nous redirigeons en entrée deread
avec l'<
opération ordinaire . Parce queread
exécuté dans notre shell principal, les variables sont définies correctement.Comme indiqué dans un commentaire, si votre objectif est littéralement de diviser une chaîne en variables, vous pouvez utiliser une chaîne ici :
Je suppose qu'il y a plus que cela, mais c'est une meilleure option s'il n'y en a pas.
la source
read a b dump <<< '1 2 3 4 5'
.cat /etc/passwd | (read -r line ; echo $line)
. Mais à côtéecho
de ce$line
qui est pas rien mis de pipeline à l' écran, parce que la valeur a été existait juste entre parenthèses (sous - shell). J'espère que ça aide quelqu'un.Ce n'est pas un
bash
bug carPOSIX
permet à la foisbash
et lesksh
comportements, conduisant à la fâcheuse différence que vous observez.http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12
De plus, chaque commande d'un pipeline multi-commandes se trouve dans un environnement de sous-shell; cependant, en tant qu'extension, une ou toutes les commandes d'un pipeline peuvent être exécutées dans l'environnement actuel. Toutes les autres commandes doivent être exécutées dans l'environnement shell actuel.
Cependant, avec
bash 4.2
et plus récent, vous pouvez définir l'lastpipe
option dans des scripts non interactifs pour obtenir le résultat attendu, par exemple:Production:
la source
lastpipe
est qu'il ne fonctionne pas dans d'autres coques (par exemple, tiret). il n'y a fondamentalement aucun moyen de faire ce portable à court de tout exécuter dans ce sous-shell, voir stackoverflow.com/questions/36268479/…