Используя трубы (|
) в Linux я могу перенаправить цепочку стандартного ввода в один или несколько выходных потоков.
я могу использовать tee
чтобы разделить вывод на отдельные подпроцессы.
Есть ли команда для объединения двух входных потоков?
Как мне это сделать? Как работает diff?
Лично мой любимый (требует bash и других вещей, которые стандартны для большинства дистрибутивов Linux)
Детали могут во многом зависеть от того, что выводят две вещи и как вы хотите их объединить ...
Содержимое command1 и command2 друг за другом в выводе:
cat <(command1) <(command2) > outputfile
Или, если обе команды выводят альтернативные версии одних и тех же данных, которые вы хотите видеть рядом (я использовал это с snmpwalk; числа с одной стороны и имена MIB с другой):
paste <(command1) <(command2) > outputfile
Или, если вы хотите сравнить вывод двух похожих команд (скажем, найти в двух разных каталогах)
diff <(command1) <(command2) > outputfile
Или, если это какие-то упорядоченные выходы, объедините их:
sort -m <(command1) <(command2) > outputfile
Или запустите обе команды одновременно (хотя может немного запутать):
cat <(command1 & command2) > outputfile
Оператор <() устанавливает именованный канал (или / dev / fd) для каждой команды, направляя вывод этой команды в именованный канал (или ссылку на дескриптор файла / dev / fd) и передает имя в командной строке. Есть эквивалент с> (). Вы могли сделать: command0 | tee >(command1) >(command2) >(command3) | command4
для одновременной отправки вывода одной команды, например, четырем другим командам.
Вы можете добавить две пары к другой с помощью cat
, как показывает горилла.
Вы также можете создать FIFO, направить в него вывод команд, а затем прочитать из FIFO любой другой программой:
mkfifo ~/my_fifo
command1 > ~/my_fifo &
command2 > ~/my_fifo &
command3 < ~/my_fifo
Особенно полезно для программ, которые будут только записывать или читать файл, или смешивать программы, которые выводят только стандартный вывод / файл, с одним, который поддерживает только другой.
(tail -f /tmp/p1 & tail -f /tmp/p2 ) | cat > /tmp/output
/tmp/p1
и /tmp/p2
ваши входные трубы, а /tmp/output
это выход.
Для этого я создал специальную программу: fdlinecombine
Он читает несколько каналов (обычно программные выходы) и записывает их в стандартный вывод линейно (вы также можете переопределить разделитель)
По-настоящему крутая команда, которую я использовал для этого, - tpipe
, вам может потребоваться скомпилировать, потому что это не так часто. Он действительно хорош для того, чтобы делать именно то, о чем вы говорите, и он настолько чистый, что я обычно его устанавливаю. Страница руководства находится здесь http://linux.die.net/man/1/tpipe . Текущая загрузка находится в этом архиве http://www.eurogaran.com/downloads/tpipe/ .
Это используется так,
## Reinject sub-pipeline stdout into standard output:
$ pipeline1 | tpipe "pipeline2" | pipeline3
Будьте осторожны здесь; простое их выделение приведет к смешиванию результатов способами, которые вы, возможно, не захотите: например, если это файлы журнала, вам, вероятно, действительно не нужно, чтобы строка из одного вставлялась посередине строки из другого. Если это нормально, тогда
хвост -f / tmp / p1 / tmp / p2> / tmp / output
буду работать. Если это не хорошо, тогда вам нужно будет найти что-то, что будет выполнять буферизацию строк и выводить только полные строки. Системный журнал делает это, но я не уверен, что еще может.
EDIT: оптимизация для небуферизованного чтения и именованных каналов:
учитывая / tmp / p1, / tmp / p2, / tmp / p3 как именованные каналы, созданные «mkfifo / tmp / pN"
хвост -q -f / tmp / p1 / tmp / p2 | awk '{print $ 0> "/ tmp / p3"; закрыть ("/ tmp / p3"); fflush ();} '&
теперь таким образом мы можем прочитать выходной именованный канал "/ tmp / p3" небуферизованный по :
хвост -f / tmp / p3
есть небольшая ошибка сортировки, вам нужно "инициализировать" 1-й входной канал / tmp / p1:
эхо -n> / tmp / p1
чтобы хвостик сначала будет принимать входные данные от 2-го канала / tmp / p2 и не ждать, пока что-то поступит в / tmp / p1. это может быть не так, если вы уверены, что / tmp / p1 получит ввод первым.
Также необходима опция -q, чтобы хвостик не выводит мусор об именах файлов.
Лучшая программа для этого - lmerge
. В отличие от ответа Freihart, он ориентирован на линию, поэтому результат двух команд не будет сбивать друг друга. В отличие от других решений, он справедливо объединяет ввод, поэтому никакая команда не может доминировать над выводом. Например:
$ lmerge <(yes foo) <(yes bar) | head -n 4
Дает результат:
foo
bar
foo
bar