grep не выводит до EOF, если трубопровод проходит через cat

Для aptitude-базированного пакета-{backup, restore}, смотрите этот ответ serverfault. Для {deborphan-based package backup, aptitude-based package restore}, смотрите совет от Богдана Токовенко (и др.) .

19
05.09.2018, 18:08
3 ответа

Когда (по крайней мере вывод GNU)grepне является терминалом, он буферизует свой вывод, что и вызывает поведение, которое вы видите. Вы можете отключить это либо с помощью опции GNU grep--line-buffered:

.
( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | grep --line-buffered LINE | cat

или утилита stdbuf:

( echo "LINE 1" ; sleep 1 ; echo "LINE 2" ; ) | stdbuf -oL grep LINE | cat

Отключить буферизацию в канале содержит дополнительную информацию по этой теме.

39
27.01.2020, 19:44

Используйте

grep --line-buffered

чтобы grep не буферизовал более одной строки за раз.

7
27.01.2020, 19:44

Упрощенное объяснение

Как и многие утилиты, это не является чем-то особенным для одной программы, grepварьирует свой стандартный вывод между строковой буферизацией и полной буферизацией . В первом случае библиотека C буферизует выходные данные в памяти до тех пор, пока либо буфер, содержащий эти данные, не будет заполнен, либо к нему не будет добавлен символ перевода строки (, либо программа не завершится чисто ), после чего она вызывает write()для фактического записать содержимое буфера. В последнем случае только переполнение буфера памяти in -(или чистое завершение программы )вызывает write().

Более подробное объяснение

Это хорошо -известное, но несколько неверное объяснение. На самом деле стандартный вывод не буферизуется строкой, а буферизуется умно в библиотеке GNU C и библиотеке C BSD.Стандартный вывод также сбрасывается при чтении стандартного ввода исчерпывает его в -буфере памяти (предварительного -чтения ввода )и Библиотека C должна вызвать read(), чтобы получить дополнительные входные данные и , она читает начало новой строки. (Одной из причин этого является предотвращение взаимоблокировки, когда другая программа подключается к обоим концам фильтра и ожидает, что сможет работать со строкой -за строкой -, чередуя запись в фильтр и чтение из него; как, например, «сопроцессы» в GNU awk.)

Влияние библиотеки C

grepи другие утилиты делают это — или, точнее, библиотеки C, которые они используют, делают это, потому что это определенная особенность программирования на языке C — на основе того, что они определяют как их стандартный вывод. Если (и только если )это не интерактивное устройство, они выбирают полную буферизацию, в противном случае выбирают умную буферизацию. Канал считается не интерактивным устройством, потому что определение интерактивного устройства, по крайней мере, в мире Unix и Linux, по сути, является вызовом isatty(), возвращающим true для соответствующего файлового дескриптора.

Обходные пути для отключения полной буферизации

Некоторые утилиты, такие как grep, имеют уникальные параметры, такие как --line-buffered, которые изменяют это решение, которое, как вы видите, имеет неправильное -название. Но исчезающе малая доля программ-фильтров, которые можно было бы использовать, на самом деле имеют такую ​​возможность.

В более общем смысле можно использовать инструменты, которые копаются во внутренностях библиотеки C и изменяют процесс принятия решений, (которые имеют проблемы с безопасностью, если для изменяемой программы установлен -UID, а также специфичны для конкретных библиотек C и действительно относятся к программам, написанным на языке C или наложенным на него ),или такие инструменты, как ptybandage, которые не изменяют внутренностей программы, а просто вставляют псевдо-терминал -в качестве стандартного вывода, так что решение становится "интерактивным", чтобы влиять на это.

Дополнительная литература

26
27.01.2020, 19:44

Теги

Похожие вопросы