`tee` и `bash` обрабатывают порядок замены

`tee` и `bash` обрабатывают порядок замены

Я бы предположил, что этот код выведет "уф" первый:

echo foo | tee >(rev) | ( sleep 1 ; cat ; )

Выход:

foo
oof

Увеличение sleepвремени не меняет порядок. Почему это не работает?


Обратите внимание, что другие инструментыделатьработать как положено,например: echo foo | pee rev 'sleep 1 ; cat'.

решение1

В

echo foo | tee >(rev) | (sleep 1; cat)

В bashпохоже на ksh, но в отличие от zsh, стандартный вывод revтакже является каналом к (sleep 1; cat)​​.

echo, tee, revи (...)подоболочка запускаются одновременно, но teeпишут foo\nв stdoutдоканал в rev, так что в любом случае, revбудет писать oofв канал после teewrites foo, так что oofможет быть только последним. Задержка catне имеет инцидентности.

Если вы хотели получить результатrev нетчтобы пройти по каналу к (sleep 1; cat), вы бы использовали zshили сделали:

{ echo foo 3>&- | tee >(rev >&3 3>&-) 3>&- | (sleep 1; cat) 3>&-; } 3>&1

Обратите внимание, что в нем zshтакже есть встроенная функция, поэтому вы можете сделать следующее:teemultios

echo foo > >(rev) > >(sleep 1; cat)

Однако в:

echo foo > >(rev) | (sleep 1; cat)

Вывод revбудет пройден cat(что сбивает с толку, учитывая, что в данном случае этого не происходит echo foo >(echo bar) | (sleep 1; cat)).

решение2

Использование двух bashподстановок процессов (вместо одной, а затем конвейера) с последующим сбросом STDOUT в /dev/null работает так, как и ожидалось:

echo foo | tee >(rev) >( sleep 1 ; cat ; ) > /dev/null ; sleep 1

Выход:

oof
foo

Примечания:

  • the 2-й sleepпредотвращает "фу" не печатается после командной строки.
  • Уменьшение sleepчисла задержек до некоторого оптимального значения должно быть лучше, но я не уверен, каким должно быть это число. 1немного медленно, но, похоже, всегда работает; .01не всегда работает (то есть выходные данные иногда находятся в неправильном порядке), .1похоже, работает хорошо.

Связанный контент