Tuyau B à D? - A && B || C | ré

14

Existe-t-il un moyen de réécrire la structure de commande A && B || C | Dafin que B ou C soit canalisé dans D?

Avec la commande actuelle, seuls B ou C et D sont exécutés.

Par exemple:

entrez la description de l'image ici

Philip Kirkbride
la source

Réponses:

31

Oui, en bash, vous pouvez utiliser des parenthèses:

(A && B || C) | D

De cette façon, la sortie de A && B || Csera canalisée D.

utopiabound
la source
6
Ou A && (B || C) | D, si vous ne voulez pas que B, C ou D s'exécute lorsque A échoue
zwol
2
Vous pouvez également utiliser des parens dans sh:)
EKons
Il n'est pas clair si l'utilisation de parenthèses à la place des accolades était une décision intentionnelle (si oui, quels sont les avantages?) Ou simplement un oubli. Pourriez-vous expliquer?
Tom Fenech
@TomFenech Parens provoque l'exécution de l'expression dans un sous-shell, qui est un (seul) processus distinct du POV du reste du script. Par conséquent, quelle que soit la sortie de l'expression à l'intérieur des parens, elle sera canalisée ensemble. (Puisque Ac'est à l'intérieur du sous-shell, cela comprend également A.)
jpaugh
1
@jpaugh Je pense que votre point sur l'isolement est bon, mais la sortie serait acheminée de la même manière lorsque vous utilisez des accolades, n'est-ce pas?
Tom Fenech
14

Vous pouvez écrire ceci comme

if A; then B; else C; fi | D

Vous dites que vous voulez exécuter soit Bou C, mais que vous A && B || Cn'y arrivez pas. Si Aréussit, mais Bs'exécute et échoue, il s'exécute C.

Remarque 1: si vous pouvez garantir en quelque sorte que cela Bréussit toujours et que vous souhaitez vous en tenir à une version courte, alors j'opterais toujours pour

{ A && B || C; } | D

plus ( ... ), car ce dernier oblige inutilement à créer un nouveau sous-shell, qui peut ou non être optimisé.

Remarque 2: les deux formes supposent qu'il Ane produit aucune sortie, ce qui est vrai dans votre exemple mais pas nécessairement en général. Cela peut être évité en

A; if [ "$?" -eq 0 ]; then B; else C; fi | D
hvd
la source
Êtes-vous sûr que { … }cela ne force pas la création d'un sous-shell à cause du tuyau? J'observe le comportement suivant: pgrep bashet pgrep bash | catet if true; then pgrep bash; fiet { pgrep bash; }ont une ligne de sortie; ( pgrep bash; )et ( pgrep bash; ) | catet { pgrep bash; } | catet if true; then pgrep bash; fi | catont deux lignes de sortie.
wchargin
@wchargin ... | ...provoque la création d' un sous-shell, c'est inévitable. ( ... ), du moins en théorie, provoque la création d' un sous-shell supplémentaire qui { ...; }évite, mais c'est ce que je voulais dire par "peut ou non être optimisé": il est possible que dans ce cas particulier, le shell se rend compte que cela n'a pas d'importance, le l'effet serait le même.
hvd
5

La réponse de l'accepteur est correcte mais elle ne couvre pas le cas d'utilisation potentiel pour ne pas avoir la sortie de Acomme entrée de D. Pour y parvenir, vous aurez besoin d'une redirection de flux en Afonction de vos besoins.

  • Si vous souhaitez supprimer la sortie de Atoute façon:

    { A >/dev/null && B || C; } | D
  • Si vous voulez voir la sortie de Asur le terminal:

    { A >/dev/tty && B || C; } | D
  • Si vous avez besoin de la sortie de Acomme entrée d'une commande suivante, Evous aurez besoin d'un groupe de commandes supplémentaire et d'une redirection de flux:

    { { A >&3 && B || C; } | D; } 3>&1 | E

Si tout cela vous semble trop mystérieux (comme c'est le cas pour moi), je vous recommande d'utiliser la variable shell spéciale pour l'état de sortie de Aet de travailler avec cela:

A
if [ $? -eq 0 ]; then
  B
else
  C
fi |
D

Si vous voulez être plus concis mais pas trop mystérieux, je suggère ceci:

A; { [ $? -eq 0 ] && B || C; } | D

(Voir aussi la dernière partie de la réponse de hvd que je n'ai pas remarquée lorsque j'ai écrit ma réponse d'origine.)

David Foerster
la source
Ma réponse couvre cela. Voyez ce que j'ai mis dans ma "Note 2:", où je suis simplement Asorti du pipeline.
hvd
@hvd: Vous avez raison et merci de m'avoir signalé cette partie de votre réponse! J'ai modifié ma réclamation et vous ai fait crédit en conséquence.
David Foerster