Чому мені потрібно уникати символів регулярних виразів у sed, щоб їх інтерпретувати як символи регулярних виразів?


11

Здається, наприклад,
cat sed_data.txt | sed 's/\b[0-9]\{3\}\b/NUMBER/g'
що я повинен уникати символів, щоб формувати регулярний вираз. У цьому випадку мені довелося уникати брекетів, щоб не раз трактуватись.
Чому? Я очікував, що все буде мати виразний характер, якщо не врятується. Тобто навпаки.


З'явився пост про пошук у Vim, який дещо висвітлює це питання, коротка версія - "це залежить від виконання команди" ... unix.stackexchange.com/questions/90345/…
Drav Sloan

@DravSloan: Я не впевнений, що це те саме. У Vim ви шукаєте текст за замовчуванням, і вам потрібно втекти, щоб шукати regex. Але в цьому випадку формат s/regex//gвже очікує регулярний вираз, і я би сподівався, що це текст, який буде потрібен щоб уникнути
Джим

Відповіді:


14

Це тому, що sedвикористовуються POSIX BRE (базові регулярні вирази) на відміну від ERE (Extended Regular вирази), до яких ви, мабуть, звикли від Perl або друзів.

На sed(1)чоловіковій сторінці:

REGULAR EXPRESSIONS
       POSIX.2 BREs should be supported, but they aren't completely because of
       performance problems.  The \n sequence in a regular expression  matches
       the newline character, and similarly for \a, \t, and other sequences.

Відповідна цитата з вищенаведеного посилання:

Основні регулярні вирази або смак BRE стандартизують аромат, аналогічний тому, який використовується традиційною командою grep для UNIX. Це майже найстаріший аромат регулярного виразу, який досі використовується. Одне, що виділяє цей аромат, - це те, що більшість метахарактерів потребують зворотній косої риси, щоб надати метахарактеру свій аромат. Більшість інших ароматів, включаючи POSIX ERE, використовують зворотний нахил, щоб придушити значення метахарактерів.

Дослівне цитування з коментаря Крейга Сандерса :

Зауважте, що в GNU sed принаймні ви можете сказати sed використовувати розширені регулярні вирази з опцією -r або --regexp-розширений командний рядок. Це корисно, якщо ви хочете уникнути зловживання скриптом sed з надмірним втечею.


1
Зауважте, що в GNU sed принаймні ви можете сказати sed використовувати розширені зворотні параметри з параметром -rабо --regexp-extendedкомандного рядка. Це корисно, якщо ви хочете уникнути зловживання скриптом sed з надмірним втечею.
cas

@CraigSanders Дякую за це. Додано для відповіді.
Джозеф Р.

@CraigSanders, інші sedреалізації (коли вони підтримують ERE, в основному BSD), як правило, використовують -Eдля цього (що має набагато більше сенсу, оскільки це той же варіант, що і для grep. Чому GNU sedвибрав -r, для мене таємниця).
Стефан Шазелас

так, таємниця і для мене. Було б більше сенсу використовувати -E. а потім додайте -F, -G та -P, щоб відповідати GNU grep. IMO gawk також виграє від тих же аргументів RE ... або, принаймні, -P.
cas

12

Це з історичних причин.

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) {/і не було підстав для втечі, (оскільки це не було оператором РЕ. Таким чином, введення нового \(або \{оператора не порушує зворотну сумісність, оскільки малоймовірно зламати існуючий сценарій, використовуючи старіший синтаксис.

Отже, ось що було зроблено. Пізніше, \(...\)спочатку додавали лише s edкоманду виконувати такі речі, як s/foo\(.\)/\1bar/і пізніше grep '\(.\)\1'(але не підвіконня \(xx\)*).

У UnixV7 (1979, так що майже через десятиліття пізніше) у новій формі додано нову форму регулярних виразів, egrepа awkутиліти називають розширеним регулярним виразом (оскільки вони є новими інструментами, зворотна сумісність не може бути порушена). Нарешті, він забезпечив функціонал, доступний у стародавньому Кена Томпсона qed(оператор чергування |, групування (..)*) і додав декілька операторів, як +і ?(але не мав функції backref для основних регулярних виразів).

Пізніше BSD додали \<і \>(і BRE і ERE), і SysV додали \{і \}лише BRE .

Це не не набагато пізніше , ніж {та }були додані до ERE, такий розрив зворотної сумісності. Не всі додали його. Наприклад, GNU awkдо версії 4.0.0 (2011) не підтримував, {якщо не був примушений до режиму відповідності POSIX.

коли GNU grepбув написаний на початку 90-х, він додав усі смаколики як BSD, так і SysV (наприклад \<, {) і замість того, щоб мати два окремих синтаксису regexp і двигун для BRE і ERE, реалізував ті самі оператори в обох, лише BRE аналоги (, ?, {, +повинні передувати зі зворотним косою риси (щоб бути сумісним з іншими реалізаціями BRE). Ось чому ви можете робити .\+в GNU grep(хоча це не POSIX або підтримується іншими реалізаціями), а ви можете робити (.)\1в GNU egrep(хоча це не POSIX або підтримується багатьма іншими реалізаціями, включаючи GNU awk).

Додавання \xоператорів - не єдиний спосіб додати більше операторів у зворотно сумісний спосіб. Наприклад, perlвживаний (?...). Це все ще відстало, сумісне з ERE, оскільки (?=...)це не справедливо для ERE, те ж саме .*?. vimдля подібних операторів це було інакше, вводячи \@=або, .\{-}наприклад.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.