Pipe attribue une variable

19

Pour plus de simplicité, je voudrais faire:

echo cart | assign spo;
echo $spo  

Sortie: chariot

Une telle assignapplication existe-t-elle?

Je connais toutes les façons de le faire en utilisant la substitution.

MageProspero
la source
Pourquoi voulez-vous faire cela sans substitution?
Thanatos
J'aime le flux de notation polonais inversé lors de l'écriture avec des tuyaux uniquement. Je suis un codage beaucoup plus rapide et la qualité / vitesse des codes n'est pas si importante. De plus, je ne le fais pas lors du chaînage, il est plus facile de commenter des parties de la chaîne et de faire écho à la sortie actuelle plutôt que d'effacer les tiques, etc.
MageProspero
Si vous êtes préoccupé par la facilité de débogage, envisagez de placer la commande backticks sur une série de lignes distinctes. A=$( some | command | here )avec chacun de some |, command |et heresur sa propre ligne.
roaima

Réponses:

11
echo cart | { IFS= read -r spo; printf '%s\n' "$spo"; }

Fonctionnerait (stocke la sortie de echosans le caractère de fin de ligne dans la spovariable) tant qu'il echone produit qu'une seule ligne.

Vous pouvez toujours faire:

assign() {
  eval "$1=\$(cat; echo .); $1=\${$1%.}"
}
assign spo < <(echo cart)

Les solutions suivantes fonctionneraient dans les bashscripts, mais pas à l' bashinvite:

shopt -s lastpipe
echo cat | assign spo

Ou:

shopt -s lastpipe
whatever | IFS= read -rd '' spo

Pour stocker la sortie des whateverpremiers caractères NUL (les bashvariables ne peuvent pas stocker les caractères NUL de toute façon) dans $spo.

Ou:

shopt -s lastpipe
whatever | readarray -t spo

pour stocker la sortie de whateverdans le $spo tableau (une ligne par élément de tableau).

Stéphane Chazelas
la source
1
ne devrait-il pas y avoir d'espace entre IFS=et read?
caesarsol
Tous saluent la dernière pipe. De plus, un jeu de notes latérales + m (ermmm ou -m) est nécessaire à partir d'une ligne de commande, car le dernier tuyau ne fonctionne pas avec le contrôle des travaux activé.
MageProspero
17

Vous pouvez faire quelque chose comme ça, si vous utilisez bash:

echo cart | while read spo; do echo $spo; done

Malheureusement, la variable "spo" n'existera pas en dehors de la boucle while-do-done. Si vous pouvez obtenir ce que vous voulez faire à l'intérieur de la boucle while, cela fonctionnera.

Vous pouvez réellement faire presque exactement ce que vous avez écrit ci-dessus dans ATT ksh (pas dans pdksh ou mksh) ou dans le fabuleux zsh:

% echo cart | read spo
% echo $spo
cart

Donc, une autre solution serait d'utiliser ksh ou zsh.

Bruce Ediger
la source
1
Vous pouvez utiliser des coprocessus dans le Korn Shell (par exemple mksh): echo cart |& while read -p spo; do echo $spo; done(en fait mieux à utiliser while IFS= read -p -r spo; do…cependant)
mirabilos
2

Si je comprends bien le problème, vous voulez diriger la sortie standard vers une variable. C'est du moins ce que je cherchais et je me suis retrouvé ici. Alors pour ceux qui partagent mon destin:

spa=$(echo cart)

Attribue cartà la variable $spa.

zack-vii
la source
2
C'est ce qu'ils appellent la substitution, ce que le PO voulait éviter.
Dmitry Grigoryev,
Cela m'a été utile, j'avais juste besoin de l'affecter à une variable, je m'en fichais de savoir comment c'était arrivé!
Chris Marisic
1

Si vous voulez simplement sortir le flux de tuyaux actuel, utilisez-le cat.

echo cart | cat 

Si vous souhaitez continuer votre chaîne de commandes, essayez d'utiliser la teecommande pour faire écho à la sortie.

echo cart | tee /dev/tty | xargs ls

Vous pouvez utiliser un alias pour raccourcir la commande.

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
BillThor
la source
Pourquoi voudriez-vous diriger la sortie vers une plaine cat?
roaima
1
@roaima Certaines commandes reconnaissent qu'elles s'exécutent sur un terminal et se comportent différemment que si elles sortent vers un tuyau. En particulier, ils peuvent tronquer les lignes à la largeur d'écran actuelle. Pour la plupart des commandes, la commande cat est redondante.
BillThor
Ah ok, je vois maintenant ce que tu essayais d'illustrer. La echo | catconstruction m'a jeté.
roaima
1

Voici ma solution au problème.

# assign will take last line of stdout and create an environment variable from it
# notes: a.) we avoid functions so that we can write to the current environment
#        b.) aliases don't take arguments, but we write this so that the "argument" appears
#            behind the alias, making it appear as though it is taking one, which in turn
#            becomes an actual argument into the temporary script T2.
# example: echo hello world | assign x && echo %x outputs "hello world"
alias assign="tail -1|tee _T1>/dev/null&&printf \"export \\\$1=\$(cat _T1)\nrm _T*\">_T2&&. _T2"
Brian Kramer
la source