Existe-t-il un moyen de réécrire la structure de commande A && B || C | D
afin que B ou C soit canalisé dans D?
Avec la commande actuelle, seuls B ou C et D sont exécutés.
Par exemple:
Existe-t-il un moyen de réécrire la structure de commande A && B || C | D
afin que B ou C soit canalisé dans D?
Avec la commande actuelle, seuls B ou C et D sont exécutés.
Par exemple:
Réponses:
Oui, en bash, vous pouvez utiliser des parenthèses:
(A && B || C) | D
De cette façon, la sortie de A && B || C
sera canalisée D
.
sh
:)
A
c'est à l'intérieur du sous-shell, cela comprend également A
.)
Vous pouvez écrire ceci comme
if A; then B; else C; fi | D
Vous dites que vous voulez exécuter soit B
ou C
, mais que vous A && B || C
n'y arrivez pas. Si A
réussit, mais B
s'exécute et échoue, il s'exécute C
.
Remarque 1: si vous pouvez garantir en quelque sorte que cela B
ré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 A
ne 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
{ … }
cela ne force pas la création d'un sous-shell à cause du tuyau? J'observe le comportement suivant: pgrep bash
et pgrep bash | cat
et if true; then pgrep bash; fi
et { pgrep bash; }
ont une ligne de sortie; ( pgrep bash; )
et ( pgrep bash; ) | cat
et { pgrep bash; } | cat
et if true; then pgrep bash; fi | cat
ont deux lignes de sortie.
... | ...
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.
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 A
comme entrée de D
. Pour y parvenir, vous aurez besoin d'une redirection de flux en A
fonction de vos besoins.
Si vous souhaitez supprimer la sortie de A
toute façon:
{ A >/dev/null && B || C; } | D
Si vous voulez voir la sortie de A
sur le terminal:
{ A >/dev/tty && B || C; } | D
Si vous avez besoin de la sortie de A
comme entrée d'une commande suivante, E
vous 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 A
et 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.)
A
sorti du pipeline.
A && (B || C) | D
, si vous ne voulez pas que B, C ou D s'exécute lorsque A échoue