Почему некоторые команды регулярных выражений имеют противоположные интерпретации '\' с различными символами?

10

Взять, к примеру, эту команду:

find . -regex ".*\.\(cpp\|h\)"

Это найдет все файлы .h и .cpp в вашем каталоге. Символ периода '.' в регулярных выражениях обычно означает «любой символ». Чтобы он соответствовал только фактическому периоду, вы должны экранировать его, используя символ обратной косой черты '\'.

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

Теперь возьмите скобки и строку «или», являясь символами '(', ')' и '|' соответственно. Они также имеют специальные значения, используемые для группировки регулярных выражений. Однако, чтобы получить особое значение, символы должны быть экранированы с помощью обратной косой черты! Без обратной косой черты символы имеют значение фактического символа, который он представляет.

Почему это "." трактуется иначе, чем '(', ')' и '|'?

Кори Кляйн
источник

Ответы:

12

Ответ действительно "просто потому что". Существует целый ряд различных синтаксисов регулярных выражений, и хотя они имеют схожий внешний вид и, как правило, основы одинаковы, они различаются по частоте.

Исторически, у каждого инструмента была своя новая реализация, делающая то, что автор считал лучшим. Существует баланс между тем, чтобы делать персонажей особенными с экранированием и без него - слишком много символов, которые «естественно особенные», и вам в конечном итоге приходится все время избегать их, чтобы соответствовать им; или, наоборот, вам в конечном итоге понадобится несколько экранированных символов для использования общего синтаксиса регулярных выражений, например (). И все, кто писал программу, решили, как это сделать, исходя из потребностей того, с чем их программа совпала, от того, что, по их мнению, было правильным подходом, и от фазы луны.

Есть попытка стандартизации из POSIX, который определяет « базовые регулярные выражения » и « расширенные регулярные выражения ». Удивительно, они работают в обратном направлении друг от друга в отношении \- иногда , но не с идеальной последовательностью.

Регулярные выражения Perl стали еще одним стандартом де-факто по двум причинам: во-первых, они очень гибкие и мощные, а во-вторых, они на самом деле довольно нормальные , с такими соглашениями, как "\ всегда экранируется не алфавитно-цифровым символом".

В GNU Find есть -regextypeопция, в которой вы можете изменить используемый синтаксис регулярного выражения. К сожалению, «perl» не вариант, по крайней мере, в той версии, которую я нашел. (По умолчанию, не удивительно, из GNU, «emacs», и этот синтаксис задокументирован здесь .)

mattdm
источник