Не глючит ли sed, когда pattern является новой строкой для команды удаления?

Моя цель - напечатать содержимое файла до (и исключая) определенного шаблона, и я использую следующее, которое работает как ожидается (даже если шаблон ^$):

sed -n '/pattern/!p;//q' file

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

sed '/pattern/d;//q' file  

который снова работает, как ожидалось, за исключением случаев, когда /pattern/ относится к пустой строке, как в /^$/ и в этом случае он добавляет пустую строку к выводу, что странно.

Файл, очевидно, содержит пустую строку в моем случае, где я хочу разделить содержимое.

Есть идеи, почему это происходит? Является sed глючит для этого крайнего случая? (дополнительный //q немедленно завершает работу, чтобы сэкономить время обработки при использовании больших файлов)

sed --version возвращается sed (GNU sed) 4.5

2 ответа

Решение

После дальнейших исследований не существует выигрышного решения:

sed '/^$/,$d' file

это лучшее, что я мог найти с точки зрения компактности, с единственным недостатком, что он будет обрабатывать весь fileчто в некоторых случаях может быть нежелательным (например, большой)

sed '/^$/,$d;//q' file

добавление типичной команды выхода не помогает, так как более ранний диапазон уже охватывает весь file

sed '/^$/q' file
sed '/^$/Q' file

эти предложения, хотя и очень компактны, не идеальны (из-за дополнительного вывода / переносимости)

sed -n '/^$/q;p' file

это еще одно предложение, которое я также нашел самостоятельно в то же время, и это несколько хорошо, учитывая, что оно прекратит работу, как только будет найден паттерн, хотя я надеялся избавиться от -n вариант, с которого я начал все это...

С GNU sed вы можете запустить

sed '/pattern/Q' file

q команда печатает пространство шаблона перед выходом, Q Команда завершается молча.

Я думаю, что отрицаемая команда !p позволяет избегать q распечатать шаблон пространства.

sed -n '/pattern/!p;//q' file  

-n вариант избегает q распечатать шаблон пространства. Другие строки печатаются, потому что адрес отрицается, поэтому p Команда применяется ко всем строкам, кроме тех, которые содержат /pattern/, Другой способ написать это будет

sed -n '/pattern/q;p' file

Когда матч pattern, выйти (без печати из-за -n опция). Все остальные строки печатают.

В этом другом сценарии d Команда удаляет все пространство шаблона и переходит непосредственно к началу sed загружен скрипт с новой строкой из ввода.

sed '/pattern/d;//q' file  

edit- в этом случае я думаю //q никогда не будет достигнута, когда есть совпадение.

echo -e 'one\ntwo\nthree\n\nfour\n\n'|sed '/^$/d;//q'
one
two
three
four

Может быть, строка не пуста, запустить cat -vet file чтобы увидеть, если есть что-то.

Новый sed версия 4.7 имеет новую опцию --debug, очень полезно посмотреть, как работает sed.

Другие вопросы по тегам