Есть ли способ передать вывод одной программы в две другие программы?

28

Извините, если это глупый вопрос, но я пытаюсь сделать что-то вроде этого, но в одной строке:

$ prog1 | prog2
$ prog1 | prog3

Итак, я в основном хочу выполнить prog1 и направить вывод в prog2 и prog3 отдельно (не в цепочку). Сначала я пытался использовать tee, но это казалось неправильным, потому что он выводил вывод в файл (а это не то, что мне нужно).

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

В какой-то момент я, возможно, захочу расширить это, чтобы передать вывод более чем двум программам, но сейчас я просто начинаю с простого.

$ prog1 | prog2
$ prog1 | prog3
$ prog1 | prog4
...
Longda
источник
Я думаю, что Zsh может сделать это.
Кит

Ответы:

28

Процесс замещения.

... | tee >(prog2) | ...
Игнасио Васкес-Абрамс
источник
1
IIRC, который является расширением bash и не встречается в стандартном POSIX sh.
Саймон Рихтер
6
@SimonRichter Это расширение ksh93, также встречающееся в bash и zsh.
Жиль "ТАК ... перестать быть злым"
16

Подобно ответу Игнасио, вы можете использовать временный именованный канал, используя mkfifo(1).

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

Это немного более многословно, но будет работать в системах, в которых нет замены процесса, например dash. Это sleep 1для обработки любых условий гонки.

Arcege
источник
6

Существует небольшая утилита PTEE , которая делает работу:

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

Вместо записи в файлы ptee записывает все файлы, которые указаны в командной строке.

Ptee является частью pipexec .

Андреас Флорат
источник
4

Вам не нужны никакие файлы или специальные файлы или что-то подобное - в любом случае, не в Linux:

% { 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

Я пометил результаты, grepвыделенные для меня, чтобы показать, что они были не только тремя результатами из одного потока, но и результатом отдельных grepсовпадений процессов.

mikeserv
источник