Gibt es eine Möglichkeit, die Ausgabe eines Programms in zwei andere Programme umzuleiten?

28

Es tut mir leid, wenn dies eine dumme Frage ist, aber ich versuche, so etwas in einer Zeile zu erreichen:

$ prog1 | prog2
$ prog1 | prog3

Ich möchte also grundsätzlich prog1 ausführen und die Ausgabe separat an prog2 und prog3 leiten (keine verkettete Pipe). Zuerst habe ich versucht, tee zu verwenden, aber das schien nicht richtig zu sein, weil die Ausgabe in eine Datei geschrieben wurde (was nicht das ist, was ich will).

$ prog1 | tee prog2 | prog3 # doesn't work - creates file "prog2"

Irgendwann möchte ich wahrscheinlich die Ausgabe auf mehr als zwei Programme ausdehnen, aber ich fange gerade erst einfach an.

$ prog1 | prog2
$ prog1 | prog3
$ prog1 | prog4
...
longda
quelle
Ich denke, zsh kann das.
Keith,

Antworten:

28

Prozessersetzung.

... | tee >(prog2) | ...
Ignacio Vazquez-Abrams
quelle
1
IIRC, eine Bash-Erweiterung, die in POSIX sh nicht enthalten ist.
Simon Richter
6
@SimonRichter Dies ist eine ksh93-Erweiterung, die auch in bash und zsh enthalten ist.
Gilles 'SO- hör auf böse zu sein'
16

Ähnlich wie bei Ignacio können Sie mit eine temporäre Named Pipe verwenden mkfifo(1).

mkfifo /tmp/teedoff.$$; cmd | tee /tmp/teedoff.$$ | prog2 & sleep 1; prog3 < /tmp/teedoff.$$; rm /tmp/teedoff.$$

Es ist etwas ausführlicher, aber es funktioniert auf Systemen, die keine Prozessersetzung haben, wie z dash. Die sleep 1ist auf eventuelle Rennbedingungen einzustellen.

Arcege
quelle
6

Es ist ein kleines Programm PTEE , die die Arbeit erledigt:

prog1 | ptee 2 3 4 2> >(prog2) 3> >(prog3) 4> >(prog4)

Anstatt in Dateien zu schreiben, schreibt ptee in alle fds, die in der Kommandozeile angegeben sind.

ptee ist ein Teil von pipexec .

Andreas Florath
quelle
4

Sie brauchen keine Bashismen, keine speziellen Dateien oder ähnliches - unter Linux sowieso nicht:

% { prog1 | tee /dev/fd/3 | prog2 >&2 ; } 3>&1 | prog3 

{ { printf %s\\t%s\\t%s\\n \
    "this uneven argument list" \
    "will wrap around" to \
    "different combinations" \
    "for each line." "Ill pick out" \
    "a few words" "and grep for them from" \
    "the same stream." | 
 tee /dev/fd/3 /dev/fd/4 | 
 grep combination >&2 ; } 3>&1 |
 grep pick >&2 ; } 4>&1 | 
 grep line

different combinations  for each *line.*  Ill pick out
different combinations  for each line.  Ill *pick* out
different *combinations*  for each line.  Ill pick out

Ich habe die hervorgehobenen Ergebnisse mit einem Stern grepmarkiert, um zu zeigen, dass es sich nicht nur um drei Ergebnisse aus demselben Stream handelt, sondern auch um Ergebnisse einzelner grepProzess-Übereinstimmungen.

mikeserv
quelle