79 votes

Comment puis-je envoyer la sortie standard d'un processus à plusieurs processus à l'aide de canaux (de préférence non nommés) sous Unix (ou Windows)?

Je voudrais rediriger la sortie standard du processus proc1 vers deux processus proc2 et proc3:

          proc2 -> stdout
       /
 proc1
       \ 
         proc3 -> stdout
 

j'ai essayé

  proc1 | (proc2 & proc3)
 

mais cela ne semble pas fonctionner, à savoir

  echo 123 | (tr 1 a & tr 1 b)
 

écrit

  b23
 

à stdout au lieu de

  a23
 b23
 

127voto

dF. Points 29787

Sous unix (ou sur un mac), l'utilisation de l' tee commande:

$ echo 123 | tee >(tr 1 a)  | tr 1 b
b23
a23

Habituellement, vous devez utiliser tee pour rediriger la sortie de plusieurs fichiers, mais en utilisant >(...) vous pouvez rediriger vers un autre processus. Donc, en général,

$ proc1 | tee >(proc2) ... >(procN-1) | procN

faire ce que vous souhaitez.

Sous windows, je ne pense pas que le shell intégrée a un équivalent. Microsoft Windows PowerShell a un tee commande.

22voto

tzot Points 32224

Comme dF dit, bash permet d'utiliser l' >(…) construire l'exécution d'une commande à la place d'un nom de fichier. (Il y a aussi l' <(…) construire de substituer à la sortie d'une autre commande à la place d'un nom de fichier, mais c'est sans importance maintenant, je le mentionne juste pour être complet).

Si vous n'avez pas de bash, ou en cours d'exécution sur un système avec une ancienne version de bash, vous pouvez le faire manuellement ce que bash n', en faisant usage de FIFO fichiers.

Le générique de la façon d'obtenir ce que vous voulez, c'est:

  • décidez combien de processus devrait recevoir la sortie de votre commande, et de créer autant de Peps, de préférence sur un mondial dossier temporaire:
 les sous-processus="a b c d"
mypid=$$
 for i in $sous-processus # de cette façon, nous sont compatibles avec tous les sh-dérivé de coquillages 
faire
 mknod /tmp/pipe.$mypid.$je p
fait
  • démarrer tous vos sous-processus en attente d'entrée de la Fifo:
 for i in $sous-processus
faire
 tr 1 $i </tmp/pipe.$mypid.$j'ai & # arrière-plan!
fait
  • l'exécution de votre commande le coup de la Fifo:
 proc1 | tee $(for i in $sous-processus; do echo /tmp/pipe.$mypid.$i; done)
  • enfin, retirez le Fifo:
 for i in $sous-processus; faire rm /tmp/pipe.$mypid.$i; done

REMARQUE: pour des raisons de compatibilité, je ne l' $(…) avec backquotes, mais je n'ai pas pu écrire cette réponse (backquote est utilisé dans). Normalement, l' $(…) est assez vieux pour travailler, même dans les anciennes versions de ksh, mais si ce n'est pas le cas, placez l' part dans les backquotes.

5voto

Jay Bazuzi Points 20462

Depuis que @dF: a mentionné que PowerShell était en té, j'ai pensé montrer un moyen de faire cela dans PowerShell.

 PS > "123" | % { 
    $_.Replace( "1", "a"), 
    $_.Replace( "2", "b" ) 
}

a23
1b3
 

Notez que chaque objet sortant de la première commande est traité avant la création du prochain objet. Cela peut permettre une mise à l'échelle de très grandes entrées.

-1voto

munish Points 948

une autre façon de faire serait,

  eval `echo '&& echo 123 |'{'tr 1 a','tr 1 b'} | sed -n 's/^&&//gp'`
 

sortie:

 a23
b23
 

pas besoin de créer un sous-shell ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X