В документации POSIX sed сказано:
Перед функцией может стоять один или несколько символов '!' символы, в этом случае функция должна применяться, если адреса не выбирают пространство шаблона. Ноль или более <пробел> символов должны быть приняты до первого '!' персонаж. Не указано, могут ли символы <blank> следовать за '!' характер и соответствующие приложения не должны следовать за «!» символ с <пробелом> символов.
Итак, с любым POSIX sed мы можем:
sed -e '/pattern/!d' file
Это так же, как писать:
sed -e '/pattern/!!d' file
А !!!d
и n
восклицательных знаков все еще быть штраф (протестировано с тремя sed
версии от реликвия Toolchest ). Я не вижу никакой выгоды между несколькими, а не одним восклицательным знаком.
Почему спецификация допускает такой синтаксис и как он полезен в реальных приложениях?
Похоже, что GNU sed в этом случае не соответствует, и будет жаловаться, если мы будем использовать несколько восклицаний:
$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s
!
действует как переключатель,/pattern/!!
такой же , как/pattern/
и/pattern/!!!
тот же/pattern/!
. На FreeBSD несколько!
одинаковы.sed
могут быть сгенерированы скрипты . Учитывая POSIXsed
, это должно быть действительно простым делом, чтобы написать сценарий написанияsed
сценария. И поэтому, если у вас есть какой-то триггер для какого-то случая, который должен пометить адрес,!
не достойный того, каким было ваше действие, вы могли бы даже запустить его несколько раз для одного и того же, и при этом получить те же результаты.sed
- нет.Ответы:
sed
API примитивен - и это по замыслу. По крайней мере, он оставался примитивным по замыслу - не мог сказать, был ли он примитивно разработан в начале. В большинстве случаев написаниеsed
сценария, который при запуске выдаст другойsed
сценарий , действительно прост.sed
очень часто применяется таким образом макропроцессорами, такими какm4
и / илиmake
.(Ниже приводится весьма гипотетический вариант использования: это проблема, разработанная для решения проблемы. Если вам кажется, что это растягивается, то, вероятно, это так, но это не обязательно делает ее менее обоснованной.)
Рассмотрим следующий входной файл:
Если бы мы хотели написать
sed
скрипт, который добавлял бы слово- case к хвосту каждого подходящего слова в указанном выше входном файле, только если его можно было найти в строке в соответствующем контексте , и мы хотели бы сделать это максимально эффективно ( как должно быть нашей целью, например, во время операции компиляции), тогда мы должны предпочесть избегать применения/
регулярных выражений/
в максимально возможной степени.Одна вещь, которую мы могли бы сделать, это предварительно отредактировать файл в нашей системе прямо сейчас и никогда не вызывать его
sed
во время компиляции. Но если какое-либо из этих слов в файле должно или не должно быть включено на основе локальных настроек и / или параметров времени компиляции, то это, вероятно, не будет желательной альтернативой.Еще одна вещь, которую мы могли бы сделать, это обработать файл сейчас с помощью регулярных выражений. Мы можем создать - и включить в нашу компиляцию -
sed
сценарий, который может применять изменения в соответствии с номером строки - который обычно является гораздо более эффективным маршрутом в долгосрочной перспективе.Например:
... который записывает вывод в виде
sed
скрипта и который выглядит как ...Когда этот вывод сохраняется в исполняемом текстовом файле на моем компьютере с именем
./bang.sed
и запускается как./bang.sed ./infile
, вывод:Теперь вы можете спросить меня ... Зачем мне это делать? Почему бы мне не просто
grep
спички якоря ? Кто использует верблюжий чемодан? И на каждый вопрос, который я мог только ответить, я понятия не имею ... потому что я не знаю. До прочтения этого вопроса я никогда лично не замечал мульти! требование разбора в спецификации - я думаю, что это довольно аккуратный улов.Мульти-! вещь сделал сразу имеет смысл для меня, хотя - большая часть
sed
спецификации ориентирована просто разобраны и просто сгенерированныхsed
сценариев. Вы, вероятно, найдете требуемые\n
разделители ewline для[wr:bt{]
большего смысла в этом контексте, и если вы будете помнить об этой идее, вы могли бы лучше понять некоторые другие аспекты спецификации - (например,:
не принимать адреса иq
отказываться от принять больше, чем 1) .В приведенном выше примере я выписать определенную форму
sed
скрипт , который может только когда - либо будет читать один раз. Если вы внимательно посмотрите на него, вы можете заметить, что приsed
чтении файла редактирования он переходит от одного блока команд к следующему - он никогда не отходит и не завершает свой скрипт редактирования до тех пор, пока он полностью не завершит свой файл редактирования.Я считаю, что мульти! адреса могут быть более полезными в этом контексте, чем в некоторых других, но, честно говоря, я не могу вспомнить ни одного случая, в котором я мог бы использовать его очень хорошо - и мне
sed
это очень нравится. Я также думаю, что стоит отметить, что GNU / BSDsed
оба не справляются с этим так, как указано - это, вероятно, не тот аспект спецификации, который пользуется большим спросом, и поэтому, если реализация игнорирует его, я очень серьезно сомневаюсь, что их баги @ box будут страдать. ужасно в результате.Тем не менее, неспособность обработать это, как указано, является ошибкой для любой реализации, которая претендует на соответствие, и поэтому я думаю, что здесь требуется отсылка электронной почты в соответствующие поля для разработчиков, и я собираюсь сделать это, если вы этого не сделаете.
источник
!
будет удален в следующей спецификации , что здесь происходит!