Специальные символы в регулярных выражениях
Ниже приведён список символов, которые являются специальными в регулярном выражении.
- ‘.’ (Точка)
-
является специальным символом, соответствующим любому одиночному символу, кроме символа новой строки. Используя конкатенацию, можно составлять регулярные выражения, например ‘a.b’, которое соответствует любой трёхсимвольной строке, начинающейся с ‘a’ и заканчивающейся на ‘b’.
- ‘*’
-
сам по себе не является конструкцией; это постфиксный оператор, означающий, что предшествующее регулярное выражение должно повторяться как можно больше раз. Таким образом, ‘o*’ соответствует любому количеству символов ‘o’ (включая отсутствие ‘o’).
‘*’ всегда применяется к наименьшему возможному предшествующему выражению. Так, в ‘fo*’ повторяется ‘o’, а не ‘fo’. Оно соответствует ‘f’, ‘fo’, ‘foo’ и так далее.
При обработке конструкции ‘*’ механизм сопоставления сразу находит максимально возможное количество повторений. Затем он продолжает обработку оставшейся части шаблона. Если это не удаётся, происходит возврат с пересмотром (backtracking): некоторые совпадения конструкции с модификатором ‘*’ отбрасываются в надежде, что так удастся сопоставить оставшуюся часть шаблона. Например, при сопоставлении ‘ca*ar’ со строкой ‘caaar’ конструкция ‘a*’ сначала пытается сопоставить все три символа ‘a’; но оставшаяся часть шаблона — ‘ar’, а для сопоставления остался только ‘r’, поэтому эта попытка не удаётся. Следующий вариант — сопоставить с помощью ‘a*’ только два символа ‘a’. При таком выборе оставшаяся часть регулярного выражения успешно сопоставляется.
- ‘+’
-
является постфиксным оператором, похожим на ‘*’, но он должен сопоставить предшествующее выражение хотя бы один раз. Например, ‘ca+r’ соответствует строкам ‘car’ и ‘caaaar’, но не строке ‘cr’, тогда как ‘ca*r’ соответствует всем трём строкам.
- ‘?’
-
является постфиксным оператором, похожим на ‘*’, но он должен сопоставить предшествующее выражение либо один раз, либо ни разу. Например, ‘ca?r’ соответствует ‘car’ или ‘cr’; и больше ничему.
- ‘*?’, ‘+?’, ‘??’
-
являются нежадными вариантами операторов ‘*’, ‘+’ и ‘?’. Эти операторы сопоставляют максимально возможную подстроку (при условии, что сопоставляется всё включающее выражение), а нежадные варианты сопоставляют минимально возможную подстроку (при том же условии).
Например, регулярное выражение ‘c[ad]*a’, применённое к строке ‘cdaaada’, сопоставляет всю строку; а регулярное выражение ‘c[ad]*?a’, применённое к той же строке, сопоставляет только ‘cda’. (Наименьшее возможное совпадение для ‘[ad]*?’, позволяющее сопоставить всё выражение, здесь — ‘d’.)
- ‘[ … ]’
-
является выражением в квадратных скобках (также называемым альтернативой символов), которое начинается с ‘[’ и заканчивается ‘]’. В простейшем случае символы между скобками — это символы, которым может соответствовать данное выражение.
Так, ‘[ad]’ соответствует одному символу ‘a’ или одному символу ‘d’, а ‘[ad]*’ соответствует любой строке, состоящей только из символов ‘a’ и ‘d’ (включая пустую строку). Следовательно, ‘c[ad]*r’ соответствует ‘cr’, ‘car’, ‘cdr’, ‘caddaar’ и т. д.
В выражение в квадратных скобках можно также включать диапазоны символов, указывая начальный и конечный символы с ‘-’ между ними. Так, ‘[a-z]’ соответствует любой строчной букве ASCII. Диапазоны можно свободно сочетать с отдельными символами, как в ‘[a-z$%.]’, которое соответствует любой строчной букве ASCII, а также символам ‘$’, ‘%’ или точке. Однако конечный символ одного диапазона не должен быть началом другого; например, следует избегать ‘[a-m-z]’.
Выражение в квадратных скобках может также задавать именованные классы символов (см. Классы символов). Например, ‘[[:ascii:]]’ соответствует любому символу ASCII. Использование класса символов эквивалентно перечислению каждого символа этого класса, но на практике последнее невозможно, поскольку некоторые классы содержат тысячи различных символов. Класс символов не должен использоваться в качестве нижней или верхней границы диапазона.
Обычные специальные символы регулярных выражений не являются специальными внутри выражения в квадратных скобках. Специальными здесь являются совершенно другие символы: ‘]’, ‘-’ и ‘^’. Чтобы включить ‘]’ в выражение в квадратных скобках, поставьте его в начало. Чтобы включить ‘^’, поставьте его в любое место, кроме начала. Чтобы включить ‘-’, поставьте его в конец. Таким образом, ‘[]^-]’ соответствует всем трём этим специальным символам. Использовать ‘\’ для экранирования этих трёх символов нельзя, поскольку ‘\’ здесь не является специальным.
Следующие особенности диапазонов характерны для Emacs: POSIX допускает такое поведение, но не требует его, а программы, отличные от Emacs, могут вести себя иначе:
- Если
case-fold-searchне-nil, ‘[a-z]’ также соответствует заглавным буквам. - На диапазон не влияет последовательность сортировки локали: он всегда представляет множество символов с кодовыми точками между кодовыми точками его границ, поэтому ‘[a-z]’ соответствует только буквам ASCII, даже вне локали C или POSIX.
- Если нижняя граница диапазона больше верхней, диапазон пуст и не представляет никаких символов. Поэтому ‘[z-a]’ всегда не соответствует, а ‘[^z-a]’ соответствует любому символу, включая символ новой строки. Однако обратный диапазон всегда следует задавать от буквы ‘z’ до буквы ‘a’, чтобы было понятно, что это не опечатка; например, следует избегать ‘[+-*/]’, поскольку оно соответствует только ‘/’, а не четырём символам, которые, вероятно, имелись в виду.
- Если конечные точки диапазона являются необработанными 8-битными байтами (см. Представления текста) или если начало диапазона — символ ASCII, а конец — необработанный байт (как в ‘[a-\377]’), диапазон будет соответствовать только символам ASCII и необработанным 8-битным байтам, но не символам, отличным от ASCII. Эта возможность предназначена для поиска текста в однобайтовых буферах и строках.
- Для поиска необработанных байтов, то есть символов, принадлежащих набору символов
eight-bit(см. Наборы символов), можно использовать ‘[\200-\377]’ или ‘[\x3fff80-\x3fffff]’
Некоторые виды выражений в квадратных скобках, хотя и имеют в Emacs чётко определённое значение, не считаются удачным стилем. К ним относятся:
- Хотя границей диапазона может быть почти любой символ, лучше ограничиваться естественными последовательностями букв и цифр ASCII, поскольку большинство людей не запоминают таблицы кодов символов. Например, ‘[.-9]’ менее понятно, чем ‘[./0-9]’, а ‘[`-~]’ менее понятно, чем ‘[`a-z{|}~]’. Здесь могут помочь escape-последовательности символов Юникода; например, для большинства программистов ‘[ก-ฺ฿-๛]’ менее понятно, чем ‘[\u0E01-\u0E3A\u0E3F-\u0E5B]’.
- Хотя выражение в квадратных скобках может содержать повторяющиеся символы, лучше избегать повторов. Например, ‘[XYa-yYb-zX]’ менее понятно, чем ‘[XYa-z]’.
- Хотя диапазон может обозначать всего один, два или три символа, проще перечислить символы. Например, ‘[a-a0]’ менее понятно, чем ‘[a0]’, ‘[i-j]’ менее понятно, чем ‘[ij]’, а ‘[i-k]’ менее понятно, чем ‘[ijk]’.
- Хотя ‘-’ может стоять в начале выражения в квадратных скобках или быть верхней границей диапазона, лучше помещать ‘-’ отдельно в конец выражения в квадратных скобках. Например, хотя ‘[-a-z]’ допустимо, ‘[a-z-]’ предпочтительнее; и хотя ‘[*--]’ допустимо, ‘[*+,-]’ понятнее.
- Если
- ‘[^ … ]’
-
‘[^’ начинает инвертированное выражение в квадратных скобках, или инвертированную альтернативу символов. Оно соответствует любому символу, кроме указанных. Так, ‘[^a-z0-9A-Z]’ соответствует всем символам, кроме букв и цифр ASCII.
‘^’ не является специальным внутри выражения в квадратных скобках, если только он не стоит первым символом. Символ после ‘^’ считается первым (другими словами, ‘-’ и ‘]’ там не являются специальными).
Инвертированное выражение в квадратных скобках может соответствовать символу новой строки, если только символ новой строки не указан среди символов, которым не нужно соответствовать. Это отличается от обработки регулярных выражений в таких программах, как
grep.Можно задавать именованные классы символов так же, как и в обычных выражениях в квадратных скобках. Например, ‘[^[:ascii:]]’ соответствует любому символу, отличному от ASCII. См. Классы символов.
- ‘^’
-
При сопоставлении с буфером ‘^’ соответствует пустой строке, но только в начале строки текста, с которым выполняется сопоставление (или в начале доступной части буфера). В противном случае он ни с чем не совпадает. Таким образом, ‘^foo’ соответствует ‘foo’, находящемуся в начале строки.
При сопоставлении со строкой, а не с буфером, ‘^’ соответствует началу строки или позиции после символа новой строки.
Для совместимости с историческим поведением ‘^’ является специальным только в начале регулярного выражения или после ‘\(’, ‘\(?:’ или ‘\|’. Хотя в других контекстах ‘^’ является обычным символом, рекомендуется использовать ‘\^’ и в этих случаях.
- ‘$’
-
похож на ‘^’, но соответствует только концу строки (или концу доступной части буфера). Таким образом, ‘x+$’ соответствует последовательности из одного или нескольких символов ‘x’ в конце строки.
При сопоставлении со строкой, а не с буфером, ‘$’ соответствует концу строки или позиции перед символом новой строки.
Для совместимости с историческим поведением ‘$’ является специальным только в конце регулярного выражения или перед ‘\)’ либо ‘\|’. Хотя в других контекстах ‘$’ является обычным символом, рекомендуется использовать ‘\$’ и в этих случаях.
- ‘\’
-
выполняет две функции: экранирует специальные символы (включая ‘\’) и вводит дополнительные специальные конструкции.
Поскольку ‘\’ экранирует специальные символы, ‘\$’ — это регулярное выражение, соответствующее только ‘$’, а ‘\[’ — регулярное выражение, соответствующее только ‘[’, и так далее.
Обратите внимание, что ‘\’ также имеет специальное значение в синтаксисе чтения строк Lisp (см. Тип строк) и должен экранироваться с помощью ‘\’. Например, регулярное выражение, соответствующее символу ‘\’, — ‘\\’. Чтобы записать строку Lisp, содержащую символы ‘\\’, синтаксис Lisp требует экранировать каждый ‘\’ ещё одним ‘\’. Поэтому синтаксис чтения регулярного выражения, соответствующего ‘\’, —
"\\\\".
Для совместимости с историческим поведением оператор повторения считается обычным символом, если он стоит в начале регулярного выражения или после ‘^’, ‘\`’, ‘\(’, ‘\(?:’ или ‘\|’. Например, ‘*foo’ трактуется как ‘\*foo’, а ‘two\|^\{2\}’ — как ‘two\|^{2}’. Не рекомендуется полагаться на такое поведение; всегда используйте правильное экранирование обратной косой чертой, независимо от положения оператора повторения.
Поскольку ‘\’ не является специальным внутри выражения в квадратных скобках, он никогда не может отменить специальное значение символов ‘-’, ‘^’ или ‘]’. Не следует экранировать эти символы, когда они не имеют специального значения. Это ничего не прояснит, поскольку обратная косая черта может обоснованно стоять перед этими символами там, где они имеют специальное значение, как в ‘[^\]’ ("[^\\]" для синтаксиса строк Lisp), которое соответствует любому одиночному символу, кроме обратной косой черты.
На практике большинство символов ‘]’ в регулярных выражениях закрывают выражение в квадратных скобках и поэтому являются специальными. Однако иногда регулярное выражение может пытаться сопоставить сложный шаблон из буквальных символов ‘[’ и ‘]’. В таких случаях иногда необходимо внимательно разбирать регулярное выражение с самого начала, чтобы определить, какие квадратные скобки ограничивают выражение в квадратных скобках. Например, ‘[^][]]’ состоит из инвертированного выражения в квадратных скобках ‘[^][]’ (которое соответствует любому одиночному символу, не являющемуся квадратной скобкой), за которым следует буквальный символ ‘]’.
Точные правила таковы: в начале регулярного выражения ‘[’ является специальным символом, а ‘]’ — нет. Так продолжается до первой неэкранированной ‘[’, после которой начинается выражение в квадратных скобках; ‘[’ больше не является специальным (кроме случая, когда он начинает класс символов), а ‘]’ является специальным, если только он не следует непосредственно за специальным ‘[’ или за этим ‘[’ с последующим ‘^’. Так продолжается до следующего специального ‘]’, который не завершает класс символов. На этом выражение в квадратных скобках заканчивается, и восстанавливается обычный синтаксис регулярных выражений: неэкранированный ‘[’ снова становится специальным, а ‘]’ — нет.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Regexp-Special.html