Буферизация строки в 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
$