Буферизация строки в bash-копроке

Я пытаюсь использовать баш coproc и я сталкиваюсь с трудностями, скорее всего с буферизацией. У меня есть сложная команда, которая принимает линейно-ориентированный ввод из stdin и печатает строку в stdout для каждой строки ввода. В командной строке эта команда прекрасно работает для каждой отдельной строки, но когда я помещаю ее в сопроцессор и читаю из ${COPROC[0]} FD, чтение блоков.

Я могу воссоздать это поведение с paste, но не с cat, Я жду paste а также cat в значительной степени сделать то же самое, когда не передал никаких параметров. Это тот случай, когда выполняется прямо из командной строки:

$ cat
Hello World!<RETURN>
Hello World!^D
$ paste
Hello World!<RETURN>
Hello World!^D
$ 

(RETURN а также ^D добавлено для иллюстрации)

Но когда я кладу их в копрок, они ведут себя по-другому - cat строго буферизована, тогда как paste похоже, работает с гораздо большим буфером:

$ coproc cat
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
Hello world!
$ kill $COPROC_PID
[3]+  Terminated              coproc COPROC cat
$ 
$ coproc paste
[3] 42657
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
#### read blocks here until ^C ####

Я думаю, что причина этого в том, что paste регулирует режим буферизации в зависимости от того, к чему он подключен, тогда как cat всегда в режиме буферизации строки.

Есть ли способ заставить paste (или другая общая команда) быть буферизованной строкой в ​​coproc?


Немного поэкспериментировав, я обнаружил, что могу воссоздать похожее поведение без каких- либо процедур и вместо этого просто перебирать cat а также paste:

$ cat | cat
Hello World!<RETURN>
Hello World!^D
$ cat | paste
Hello World!<RETURN>
Hello World!^D
$ paste | cat
Hello World!<RETURN>
#### command blocks here until ^C ####

(RETURN а также ^D добавлено для иллюстрации)

  • Сначала мы трубу cat в cat и получить линию буферизации весь путь, хотя
  • Далее мы трубу cat в paste а также получить буферизацию строки, хотя
  • Наконец мы труба paste в cat и не получить буферизацию строки

Это указывает на то, что paste строка будет буферизовать свой стандартный вывод в интерактивном режиме, но в противном случае он будет использовать гораздо больший буфер.

1 ответ

Решение

Один из способов форсировать буферизацию строки - использовать stdbuf Инструмент Coreutils, если имеется:

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

Для coproc дело:

$ coproc stdbuf -oL paste
[3] 42751
$ echo 'Hello world!' >&${COPROC[1]}
$ read -ru ${COPROC[0]} line; echo $line
Hello world!
$ kill $COPROC_PID
[3]+  Terminated              coproc COPROC stdbuf -oL paste
$ 

Для простой трубы paste в cat дело:

$ stdbuf -oL paste | cat
Hello World!<RETURN>
Hello World!^D
$ 
Другие вопросы по тегам