Disons que j'ai le pipeline suivant:
cmd1 < input.txt |\
cmd2 |\
cmd4 |\
cmd5 |\
cmd6 |\
(...) |\
cmdN > result.txt
Sous certaines conditions, j'aimerais ajouter un cmd3
entre cmd2
et cmd4
. Existe-t-il un moyen de créer un type de pipeline conditionnel sans enregistrer le résultat de cmd2 dans un fichier temporaire? Je penserais à quelque chose comme:
cmd1 < input.txt |\
cmd2 |\
(${DEFINED}? cmd3 : cat ) |\
cmd4 |\
cmd5 |\
cmd6 |\
(...) |\
cmdN > result.txt
Réponses:
Juste l'habituel
&&
et les||
opérateurs:(Notez qu'aucune barre oblique inverse n'est nécessaire lorsque la ligne se termine par un tuyau.)
Mise à jour selon l'observation de Jonas .
Si cmd3 peut se terminer avec un code de sortie différent de zéro et que vous ne souhaitez
cat
pas traiter l'entrée restante, inversez la logique:la source
cat
renvoie avec un statut de sortie différent de zéro (commun lors de l'obtention d'un SIGPIPE), alorscmd3
sera exécuté. Mieux vaut utiliser si / alors / sinon comme dans la réponse de Thor ou d'autres solutions qui évitent de courircat
.if
/else
/fi
fonctionne. En supposant que tout shell Bourne-like:la source
Toutes les réponses données jusqu'à présent remplacent
cmd3
parcat
. Vous pouvez également éviter d’exécuter une commande avec:C'est POSIX, mais notez que si dans un
bash
script oùbash
n'est pas ensh
-mode (comme avec un script commençant par#! /path/to/bash
), vous devez activer le développement d'alias avecshopt -s expand_aliases
(ouset -o posix
).Une autre approche qui n'exécute toujours pas de commande inutile consiste à utiliser eval:
Ou:
Sous Linux (au moins), au lieu de
cat
, vous pouvez utiliserpv -q
lequel utilisesplice()
au lieu deread()
+write()
pour transmettre les données entre les deux canaux, ce qui évite que les données soient déplacées deux fois entre le noyau et l’espace utilisateur.la source
En tant qu'additif à la réponse acceptée par manatwork : soyez conscient du et du faux et du gotcha et de son interaction avec les flux. Par exemple,
sorties
foo
. Sans surprise,et
les deux sorties
baz
. (Notez queecho foo | grep bar
c'est faux et n'a pas de sortie). cependant,ne sort rien. Cela peut être ou ne pas être ce que vous voulez.
la source
else
(ou||
) doit agir comme une opération nulle en conservant l’entrée inchangée. Donc, en remplaçantcat
par desecho
modifications, tout ce qui rend votre code inutile. En ce qui concerne le "et-faux-ou-gotcha", je ne vois aucune interférence avec le pipeline: pastebin.com/u6Jq0bZe[[ "${DEFINED}" ]] && cmd3 || cat
,cmd3
etcat
ne sont pas mutuellement exclusivesthen
et leselse
branches du mêmeif
, mais que sicmd3
échoue, alorscat
sera également exécuté. (Bien sûr, sicmd3
réussit toujours, ou si elle consomme toutes les entrées donc il n'y a rien àstdin
pourcat
à traiter, puis il importe peu.) Si vous avez besoin à la foisthen
et leselse
branches, il est préférable d'utiliser une expliciteif
commande, non&&
et||
.J'ai eu une situation similaire que j'ai résolue avec les fonctions bash :
la source
Voici une autre solution possible:
concaténer des canaux nommés afin de créer un pseudo-pipeline:
la source
Pour référence future, si vous venez ici à la recherche de pipes conditionnelles dans le poisson , procédez comme suit:
la source