Например
cat sed_data.txt | sed 's/\b[0-9]\{3\}\b/NUMBER/g'
, я должен экранировать символы, чтобы сформировать регулярное выражение. В этом случае мне пришлось избегать скобок, чтобы их можно было интерпретировать несколько раз.
Почему? Я ожидал, что все будет символом регулярного выражения, если не сбежит. Т.е. наоборот.
11
s/regex//g
уже ожидает регулярное выражение, и я ожидаю, что это текст, который будет нуждаться в чтобы избежатьОтветы:
Это связано с тем, что
sed
используются POSIX BRE (базовые регулярные выражения) в отличие от ERE (расширенных регулярных выражений), к которым вы, вероятно, привыкли из Perl или друзей.Со
sed(1)
страницы руководства :Соответствующая цитата по вышеуказанной ссылке:
Цитируется дословно из комментария Крейга Сандерса :
источник
-r
или--regexp-extended
командной строки. Это полезно, если вы хотите избежать чрезмерного экранирования сценария sed.sed
реализации (когда они поддерживают ERE, в основном BSD)-E
вместо этого, как правило, используют для этого (что имеет гораздо больше смысла, поскольку это тот же вариант, что и дляgrep
. Почему GNUsed
выбрал-r
, для меня загадка).Это по историческим причинам.
Regexp были впервые представлены в Unix в
ed
утилите в начале 70-х годов. Хотяed
был основан наqed
осуществление которых по тем же авторов понимается более сложное регулярное выражение,ed
только понял^
,$
,[...]
,.
,*
и ,\
чтобы избежать всего вышеперечисленного.Теперь, когда возникла необходимость иметь больше операторов, нужно было найти способ представить их без нарушения обратной совместимости. Если скрипт , используемый , чтобы использовать
s
ed
команду , какs/foo() {/foo (var) {/g
заменить все экземплярыfoo() {
с ,foo(var) {
и вы ввели(
или{
оператора, что бы разорвать этот сценарий.Однако ни один скрипт не подойдет
s/foo\(\) {/foo\(var\) {/
, потому что это так же, какs/foo() {/foo(var) {/
и не было никаких причин сбегать,(
поскольку это не оператор RE. Таким образом, введение нового оператора\(
или\{
оператора не нарушает обратную совместимость, поскольку очень маловероятно, что существующий сценарий нарушит старый синтаксис.Итак, вот что было сделано. Позже,
\(...\)
был добавлен изначально только дляs
ed
команды, чтобы сделать что-то вроде,s/foo\(.\)/\1bar/
а позже какgrep '\(.\)\1'
(но не так, как\(xx\)*
).В UnixV7 (1979 год, то есть почти десятилетие спустя) в новую и регулярные выражения были добавлены новая форма регулярных выражений
egrep
иawk
утилиты, называемые расширенными регулярными выражениями (поскольку они являются новыми инструментами, обратной совместимости нарушать нельзя). Наконец, он предоставил функциональность, доступную в древнем Кене Томпсонеqed
(оператор чередования|
, группировка(..)*
), и добавил несколько операторов, таких как+
и?
(но не имел функции обратной ссылки в основных регулярных выражениях).Позже BSD добавили
\<
и\>
(и к BRE, и к ERE), а SysV добавили\{
и\}
только к BRE.Это не намного позже
{
и}
были добавлены в ERE, из-за такой нарушения обратной совместимости. Не все это добавили. Например, GNUawk
до версии 4.0.0 (2011) не поддерживала,{
пока не была переведена в режим соответствия POSIX.когда GNU
grep
был написан в начале 90-х, он добавил все вкусности от BSD и SysV (вроде\<
,{
), и вместо того, чтобы иметь два отдельных синтаксиса regexp и механизм для BRE и ERE, реализовал одинаковые операторы в обоих, только аналоги BRE(
,?
,{
,+
должны предшествовать с обратной косой черты (чтобы быть совместимым с другими реализациями BRE). Вот почему вы можете делать это.\+
в GNUgrep
(хотя это не POSIX или не поддерживается другими реализациями), и вы можете делать это(.)\1
в GNUegrep
(хотя это не POSIX или не поддерживается многими другими реализациями, включая GNUawk
).Добавление
\x
операторов - не единственный способ добавить больше операторов в обратно совместимом виде. Например,perl
используется(?...)
. Это все еще обратно совместимо с ERE, что(?=...)
недопустимо в ERE, то же самое для.*?
.vim
для аналогичных операторов сделал это по-другому, введя\@=
или,.\{-}
например.источник