2013-06-24 2 views
8

Это только гипотетический вопрос - не решение какой-либо реальной проблемы - только обучение bash.Вставить результат команды tee

С помощью команды tee возможно разделить вывод на несколько различных потоков, как:

command1 | tee >(commandA1 | commandA2 >file1) >(commandB1 | commandB2 >file2) >file0 

так графически делается следующий

    ---commandA1---commandA2--> file1 
       /
command1---tee-------> file0 
       \ 
        ---commandB1---commandB2--> file2 

Теперь, с помощью команды paste может, например,

paste file1 file2 | command3 

но опять же я могу перенаправить к выходу вставляет данные из различных программ, как:

paste <(ls) <(ls) | command3 

Возникает вопрос: можно несколько соединить два потока в один, что-то вроде

    ---commandA1---commandA2--- 
       /       \ 
command1---tee-------> file0     --- paste---command3 
       \       /
        ---commandB1---commandB2--- 

Пс: среднее без промежуточных файлов ...

+5

Не без промежуточного файла или именованного канала. См. 'Mkfifo' – SheetJS

+3

Это своего рода вопрос, который я люблю видеть - несколько, что не тривиально. К сожалению, я не знаю bash достаточно глубоко, чтобы показать, как добиться этого с помощью «названных каналов», как предложил @Nirk ... +1 – kobame

ответ

3

Вот как это сделать с именем p IPES:

trap "rm -f /tmp/file1 /tmp/file2; exit 1" 0 1 2 3 13 15 
mkfifo /tmp/file1 
mkfifo /tmp/file2 
command1 | tee >(commandA1 | commandA2 >/tmp/file1) >(commandB1 | commandB2 >/tmp/file2) >file0 
paste /tmp/file1 /tmp/file2 | command3 
rm -f /tmp/file1 /tmp/file2 
trap 0 

Рабочий пример:

$ cd -- "$(mktemp -d)" 
$ trap "rm -f pipe1 pipe2; exit 1" 0 1 2 3 13 15 
$ mkfifo pipe1 pipe2 
$ printf '%s\n' 'line 1' 'line 2' 'line 3' 'line 4' | tee \ 
>(sed 's/line /l/' | head -n 2 > pipe1) \ 
>(sed 's/line /Line #/' | tail -n 2 > pipe2) \ 
> original.txt 
$ paste pipe1 pipe2 | sed 's/\t/ --- /' 
l1 --- Line #3 
l2 --- Line #4 
$ rm pipe1 pipe2 
$ trap 0 
+0

Я не писал это, @JonathanLeffler добавил, что (прежде чем вы добавили рабочий пример) , – Barmar

+0

@ l0b0: «выйти 1» в ловушку, чтобы указать, что процесс завершился неудачно; 'exit 0' будет давать вводящее в заблуждение впечатление, что процесс преуспел. И не добавление «exit» означает «выход со статусом последней команды, которая будет« rm -f », которая будет успешной, поэтому статус выхода будет равен 0.« trap »гарантирует, что временные FIFO удаляются, когда оболочка может их удалить. Если вы убьете процесс с помощью 'kill -9', он ничего не сможет сделать для очистки. Но если вы используете HUP, INT, QUIT, PIPE или TERM (1, 2, 3, 13, 15), тогда оболочка будет очищаться за собой перед выходом. –

+0

@JonathanLeffler Что вводит в заблуждение, так это то, что вы включаете '0' в список сигналов, которые вы ловушки, что означает, что он будет работать во время обычного выхода и превратит его в неудачный выход. Но этого на самом деле не произойдет, потому что вы отключите ловушку при выходе с 'trap 0' в конце, поэтому в исходной команде trap нет смысла. – Barmar

Смежные вопросы