Вопрос или проблема
Это работает
head -c 10 /dev/zero | sed 's/\x0/x/g'
и генерирует xxxxxxxxxx
, как и ожидалось.
Затем я попробовал это:
sed 's/\x0/x/g' /dev/zero | head -c 10
и, похоже, просто зависает.
Затем я подумал, конечно, здесь нет новой строки, и sed
не может даже завершить обработку строки в пространстве шаблона, поэтому он зависает. Это причина, по которой команда выше зависает?
Но подождите, есть опция -u
:
-u, --unbuffered минимально загружает данные из входных файлов и чаще сбрасывает выходные буферы
что заставило меня думать, что это будет решением, но, похоже, оно тоже блокируется:
sed -u 's/\x0/x/g' /dev/zero | head -c 10
Означает ли это, что просто невозможно работать с sed
на бесконечном потоке?
Так получилось, что, написав вопрос, я, думаю, нашел ответ. Я удалю его, если кто-то докажет, что я ошибаюсь, и даст правильный ответ.
Я полагаю, что проблема в том, что sed
ориентирован на строки, независимо от того, являются ли разделители строк \n
или \x0
(второе возможно при передаче опции -z
, насколько я понимаю), поэтому бесконечный поток одного символа просто не является допустимым вводом для sed
, потому что это означает одно из двух:
- если этот бесконечно повторяющийся символ – это
\n
(соответственно\x0
), иsed
был запущен без (соответственно с) опцией-z
, то входной поток – это бесконечное количество пустых строк, - в противном случае, входной поток – это единственная строка, состоящая из бесконечного количества повторений этого символа.
Ответ или решение
Работа с потоками данных на уровне операционной системы и инструментов командной строки может часто вызывать вопросы и сложности, как в случае с использованием команды sed
для обработки вывода из /dev/zero
. Давайте рассмотрим, почему именно стандартные подходы не работают и каковы причины такого поведения.
Теория
sed
— это утилита обработки текстовых потоков, которая традиционно ориентирована на работу с текстовыми данными, организованными построчно. Она ожидает, что данные будут разделены символами новой строки (\n
), что позволяет утилизировать концепцию «строки» текста. Это влияние имеет смысл из контекста использования sed
для обработки файлов или вывода команд, где строковые данные преобладают.
Когда sed
получает входной поток данных, который не содержит символов новой строки, или же поток состоит из бесконечного числа повторяющихся символов без разделения на строки (как в случае с /dev/zero
), выполнение команд sed
становится проблематичным. В частности, это происходит потому, что sed
, ожидая окончания строки (символ новой строки), не может загрузить всю необходимую часть данных в свое пространство шаблона, приводя к блокировке или зависанию выполнения.
Пример
В приведенном вами примере команда head -c 10 /dev/zero | sed 's/\x0/x/g'
отлично работает, потому что команда head
ограничивает поток только первыми 10 байтами, которые затем sed
обрабатывает и заменяет нули на x
. В этом случае все данные помещаются в память, и sed
обрабатывает их как единую "строку", несмотря на отсутствие символов новой строки.
Однако при использовании команды sed 's/\x0/x/g' /dev/zero | head -c 10
, поток /dev/zero
поступает непосредственно в sed
. Тут и появляется проблема — sed
не способен определить границу строки, поскольку в данных нет символа новой строки, что заставляет его бесконечно ожидать окончания этого потока или следующего символа новой строки.
Применение
Разобравшись в теоретических основаниях проблемы и проанализировав пример, давайте рассмотрим возможные пути обхода и альтернативы, которые могут помочь в работе с подобными бесконечными потоками данных:
-
Использование
dd
: Одним из способов ограничить объем данных, поступающих вsed
, до разумной величины является использование командыdd
, которая может производить выборку ограниченного количества байт. Например:dd if=/dev/zero bs=10 count=1 | sed 's/\x0/x/g'
Здесь
dd
извлекает первые 10 байт, которые затем обрабатываютсяsed
. -
Использование опции
-z
: Другой возможностью является использование опции-z
для обработки файлов с нулевым окончанием строк. Однако, в текущем контексте она не решает проблему, поскольку ни/dev/zero
, ни потоковые преобразования на символы новой строки не изменят сути бесконечного потока данных. -
Перепроектирование задачи: Возможно, более эффективным подходом будет пересмотр технологии обработки данных. Иногда задачу, которую вы пытаетесь решить с
sed
, можно перенести в другой язык программирования или инструмент, который более удобно и гибко работает с побитными потоками данных.
Заключение
Работа с бесконечными потоками данных через sed
требует понимания его ограничений и природы входного потока. Поскольку sed
предназначен для обработки текста, эта утилита не всегда подходит для работы с данными, не структурированными как текст, с ожидаемыми символами новой строки. В таких случаях, когда требуется замена символов в бесконечном потоковом вводе, рекомендуется использовать инструменты или симуляции, более подходящие для работы на низком уровне, например, скрипты на языках программирования, способных выполнять преобразования напрямую в потоке данных.