J'essaie d'obtenir la sortie d'un tuyau dans une variable. J'ai essayé les choses suivantes:
echo foo | myvar=$(</dev/stdin)
echo foo | myvar=$(cat)
echo foo | myvar=$(tee)
Mais $myvar
est vide.
Je ne veux pas faire:
myvar=$(echo foo)
Parce que je ne veux pas engendrer de sous-shell.
Des idées?
Edit: Je ne veux pas générer un sous-shell car la commande avant le canal doit modifier les variables globales, ce qu'elle ne peut pas faire dans un sous-shell. Peut-il? La chose echo
est juste pour simplifier. C'est plus comme:
complex_function | myvar=$(</dev/stdin)
Et je ne comprends pas, pourquoi cela ne fonctionne pas. Cela fonctionne par exemple:
complex_function | echo $(</dev/stdin)
Utilisez la substitution de commande:
myvar=`echo foo`
ou
myvar=$(echo foo)
La bonne solution consiste à utiliser la substitution de commandes comme ceci:
variable=$(complex_command)
un péché
message=$(echo 'hello')
(ou d'ailleurs, message=hello
dans ce cas).
Votre pipeline:
echo 'hello' | message=$(</dev/stdin)
ou
echo 'hello' | read message
fonctionne réellement. Le seul problème est que le shell que vous utilisez exécutera la deuxième partie du pipeline dans un sous-shell. Ce sous-shell est détruit à la sortie du pipeline, donc la valeur de $message
n'est pas conservé dans Shell.
Ici, vous pouvez voir que cela fonctionne:
$ echo 'hello' | { read message; echo "$message" }
hello
... mais comme l'environnement du sous-shell est séparé (et disparu):
$ echo "$message"
(aucune sortie)
Une solution pour vous serait de passer à ksh93
ce qui est plus intelligent à ce sujet:
$ echo 'hello' | read message
$ echo "$message"
hello
Une autre solution pour bash
serait de définir l'option lastpipe
Shell. Cela ferait fonctionner la dernière partie du pipeline dans l'environnement actuel. Cependant, cela ne fonctionne pas dans les shells interactifs car lastpipe
nécessite que le contrôle des travaux ne soit pas actif.
#!/bin/bash
shopt -s lastpipe
echo 'hello' | read message
echo "$message"
Dans ksh93
, vous pouvez utiliser:
var=${
my command that updates global variable
}
C'est une forme de substitution de commande qui ne génère pas de sous-shell. Pour les commandes qui sont des commandes intégrées, au lieu de les faire écrire leur sortie dans un canal (pour lequel vous auriez besoin de différents processus pour lire et écrire sur le canal pour éviter les blocages), ksh93
ne leur fait simplement pas sortir quoi que ce soit, mais rassembler ce qu'ils auraient dû produire pour constituer l'extension.
$ ksh -c 'a=${ b=123; echo foo;}; echo "$a $b"'
foo 123
La substitution de commandes de fish
se comporte également comme ceci:
$ fish -c 'set a (set b 123; echo foo); echo $a $b'
foo 123
Dans la plupart des autres shells, vous utiliseriez un fichier temporaire:
my command that updates global variable > file
var=$(cat file) # can be optimised to $(<file) with some shells
Sous Linux et avec bash
ou zsh
(qui utilisent des fichiers temporaires pour <<<
), tu peux faire:
{ my command that updates global variable > /dev/fd/3 &&
var=$(cat<&3); } 3<<< ''