sed
API примитивен - и это по замыслу. По крайней мере, он оставался примитивным по замыслу - не мог сказать, был ли он примитивно разработан в начале. В большинстве случаев написание sed
сценария, который при запуске выдаст другой sed
сценарий , действительно прост. sed
очень часто применяется таким образом макропроцессорами, такими как m4
и / или make
.
(Ниже приводится весьма гипотетический вариант использования: это проблема, разработанная для решения проблемы. Если вам кажется, что это растягивается, то, вероятно, это так, но это не обязательно делает ее менее обоснованной.)
Рассмотрим следующий входной файл:
cat <<"" >./infile
camel
cat dog camel
dog cat
switch
upper
lower
Если бы мы хотели написать sed
скрипт, который добавлял бы слово- case к хвосту каждого подходящего слова в указанном выше входном файле, только если его можно было найти в строке в соответствующем контексте , и мы хотели бы сделать это максимально эффективно ( как должно быть нашей целью, например, во время операции компиляции), тогда мы должны предпочесть избегать применения /
регулярных выражений /
в максимально возможной степени.
Одна вещь, которую мы могли бы сделать, это предварительно отредактировать файл в нашей системе прямо сейчас и никогда не вызывать его sed
во время компиляции. Но если какое-либо из этих слов в файле должно или не должно быть включено на основе локальных настроек и / или параметров времени компиляции, то это, вероятно, не будет желательной альтернативой.
Еще одна вещь, которую мы могли бы сделать, это обработать файл сейчас с помощью регулярных выражений. Мы можем создать - и включить в нашу компиляцию - sed
сценарий, который может применять изменения в соответствии с номером строки - который обычно является гораздо более эффективным маршрутом в долгосрочной перспективе.
Например:
n=$(printf '\\\n\t')
grep -En 'camel|upper|lower' <infile |
sed " 1i${n%?}#!/usr/heirloom/bin/posix2001/sed -nf
s/[^:]*/:&$n&!n;&!b&$n&/;s/://2;\$a${n%?}q"'
s/ *cat/!/g;s/ *dog/!/g
s| *\([cul][^ ]*\).*|s/.*/\1-case/p|'
... который записывает вывод в виде sed
скрипта и который выглядит как ...
#!/usr/heirloom/bin/posix2001/sed -nf
:1
1!n;1!b1
1s/.*/camel-case/p
:2
2!n;2!b2
2!!s/.*/camel-case/p
:5
5!n;5!b5
5s/.*/upper-case/p
:6
6!n;6!b6
6s/.*/lower-case/p
q
Когда этот вывод сохраняется в исполняемом текстовом файле на моем компьютере с именем ./bang.sed
и запускается как ./bang.sed ./infile
, вывод:
camel-case
upper-case
lower-case
Теперь вы можете спросить меня ... Зачем мне это делать? Почему бы мне не просто grep
спички якоря ? Кто использует верблюжий чемодан? И на каждый вопрос, который я мог только ответить, я понятия не имею ... потому что я не знаю. До прочтения этого вопроса я никогда лично не замечал мульти! требование разбора в спецификации - я думаю, что это довольно аккуратный улов.
Мульти-! вещь сделал сразу имеет смысл для меня, хотя - большая часть sed
спецификации ориентирована просто разобраны и просто сгенерированных sed
сценариев. Вы, вероятно, найдете требуемые \n
разделители ewline для [wr:bt{]
большего смысла в этом контексте, и если вы будете помнить об этой идее, вы могли бы лучше понять некоторые другие аспекты спецификации - (например, :
не принимать адреса и q
отказываться от принять больше, чем 1) .
В приведенном выше примере я выписать определенную форму sed
скрипт , который может только когда - либо будет читать один раз. Если вы внимательно посмотрите на него, вы можете заметить, что при sed
чтении файла редактирования он переходит от одного блока команд к следующему - он никогда не отходит и не завершает свой скрипт редактирования до тех пор, пока он полностью не завершит свой файл редактирования.
Я считаю, что мульти! адреса могут быть более полезными в этом контексте, чем в некоторых других, но, честно говоря, я не могу вспомнить ни одного случая, в котором я мог бы использовать его очень хорошо - и мне sed
это очень нравится. Я также думаю, что стоит отметить, что GNU / BSD sed
оба не справляются с этим так, как указано - это, вероятно, не тот аспект спецификации, который пользуется большим спросом, и поэтому, если реализация игнорирует его, я очень серьезно сомневаюсь, что их баги @ box будут страдать. ужасно в результате.
Тем не менее, неспособность обработать это, как указано, является ошибкой для любой реализации, которая претендует на соответствие, и поэтому я думаю, что здесь требуется отсылка электронной почты в соответствующие поля для разработчиков, и я собираюсь сделать это, если вы этого не сделаете.
!
действует как переключатель,/pattern/!!
такой же , как/pattern/
и/pattern/!!!
тот же/pattern/!
. На FreeBSD несколько!
одинаковы.