2015-08-04 3 views
2

Je voudrais être capable de créer une fonction bash capable de lire le code de sortie de la commande avant le pipe. Je ne suis pas sûr qu'il soit possible d'y avoir accès.Récupère le code de sortie du dernier tube (stdin)

  • echo "1" | grep 2 renvoie un code 1 d'état
  • echo "1" | grep 1 renvoie un code d'état 0

Maintenant, je voudrais ajouter une troisième commande pour lire l'état, avec un tuyau:

  • echo "1" | grep 2 | echo $? va afficher "0", même si le code d'état est 1.

Je sais que je peux utiliser le echo "1" | grep 2 && echo "0" || echo "1", mais je préférerais l'écrire avec un tuyau.

Est-ce qu'ils quand même à le faire (ce serait encore mieux si elle travaillait sur la plupart des obus, comme bash, sh, et zsh)

+3

Pourquoi voudriez-vous utiliser un tuyau pour cela? 'echo" 1 "| grep 2; echo $? 'fonctionnerait bien. – Yannoff

+0

Parce que je pourrais aussi avoir besoin de ce qui vient de stdin. Cependant, je préfère votre solution que celle de @mattinbits – edi9999

+1

Cela ressemble à un problème XY. Pourquoi avez-vous besoin du statut de * dans * le pipeline? – chepner

Répondre

1

En bash vous pouvez le faire avec la variable PIPESTATUS

echo "1" | grep 1 
echo ${PIPESTATUS[0]} # returns 0 
echo "1" | grep 2 
echo ${PIPESTATUS[0]} # returns 0 
echo "1" | grep 2 
echo ${PIPESTATUS[1]} # returns 1 
+0

La dernière commande ne se trouve pas dans un tube. '$?' fonctionnerait beaucoup mieux parce que je veux récupérer le dernier code d'état, pas le nième – edi9999

+0

@ edi9999 le mettre dans la commande puis 'echo" 1 "| grep 2 | echo $ {PIPESTATUS [1]} ' – 123

+0

Oui mais si j'ai trois commandes au lieu de deux cela ne marcherait pas: par exemple' echo "1" | sed | grep 2 | echo $ {PIPESTATUS [1] ' – edi9999

3

Vous devez obtenir le statut de sortie avant la prochaine étape du pipeline. Quelque chose comme

exec 3> debug.txt 
{ echo "1"; echo "$?" >&3; } | long | command | here 

Vous ne pouvez pas (facilement) encapsuler cela dans une fonction, car il faudrait passer une chaîne correctement cité et l'exécuter via eval:

debug() { 
    eval "[email protected]" 
    echo $? >&3 
} 

# It looks easy in this example, but it won't take long to find 
# an example that breaks it. 
debug echo 1 | long | command | here 

Vous devez écrire la sortie l'état à un descripteur de fichier différent, sinon il interférera avec la sortie envoyée à la commande suivante dans le pipeline.