Регулярные выражения
Введение
Регулярные выражения - это широкоиспользуемый способ описания шаблонов для поиска текста и проверки соответствия текста шаблону. Специальные метасимволы позволяют определять, например, что Вы ищете подстроку в начале входной строки или определенное число повторений подстроки.
Простое сравнение
Любой символ совпадает с самим собой, если он не относится к специальным метасимволам описанным чуть ниже. Последовательность символов совпадает с такой же последовательностью во входной строке, так что шаблон "foobar" совпадет с подстрокой "foobar" во входной строке.
Если необходимо, чтобы метасимволы или escape-последовательности воспринимались как обычные символы, их нужно предварять символом "\", например, метасимвол "^" обычно совпадает с началом строк, однако, если записать его как "\^", то он будет совпадать с символом "^", "\\" совпадает с "\" и т.д.
Например:
- foobar находит 'foobar'
- \^FooBarPtr находит '^FooBarPtr'
Escape-последовательности
Любой символ может быть определен с помощью escape последовательности, так же как это делается в языках C или Perl: "\n" означает начало строки, "\t" - табуляцию и т.д.. Вообще, \xnn, где nn это последовательность шестнадцатеричных цифр, означает символ с ASCII-кодом nn. Если необходимо определить двухбайтный (Unicode) символ, используйте формат '\x{nnnn}', где 'nnnn' - одна или более шестнадцатеричных цифр.
- \xnn - символ с шестнадцатеричным кодом nn
- \x{nnnn} - символ с шестнадцатеричным кодом nnnn (более одного байта можно задавать только в режиме Unicode)
- \t - табуляция (HT/TAB), можно также \x09
- \n - новая строка (NL), можно также \x0a
- \r - возврат каретки (CR), можно также \x0d
- \f - перевод формата (FF), можно также \x0c
- \a - звонок (BEL), можно также \x07
- \e - escape (ESC), можно также \x1b
Например:
- foo\x20bar находит 'foo bar' (обратите внимание на пробел посередине)
- \tfoobar находит 'foobar' предшествуемый табуляцией
Перечни символов
Вы можете определить перечень, заключив символы в []. Перечень будет совпадать с любым одним символом перечисленным в нем. Если первый символ перечня (сразу после "[") - "^", то такой перечень совпадает с любым символом не перечисленным в перечне.
Например:
- foob[aeiou]r находит 'foobar', 'foober' и т.д. но не 'foobbr', 'foobcr' и т.д.
- foob[^aeiou]r находит 'foobbr', 'foobcr' и т.д.. но не 'foobar', 'foober' и т.д.
Внутри перечня символ "-" может быть использован для определения диапазонов символов, например a-z представляет все символы между "a" и "z", включительно.
Если Вам необходимо включить в перечень сам символ "-", поместите его в начало или конец перечня или предварите "\". Если Вам необходимо поместить в перечень сам символ "]", поместите его в самое начало или предварите "\".
Например:
- [-az] находит 'a', 'z' и '-'
- [az-] находит 'a', 'z' и '-'
- [a\-z] 'a', 'z' и '-'
- [a-z] находит все 26 малых латинских букв от 'a' до 'z'
- [\n-\x0D] находит #10, #11, #12, #13.
- [\d-t] находит цифра, '-' или 't'
- []-a] находит символ из диапазона ']'..'a'
Метасимволы
Метасимволы - это специальные символы, являющиеся важнейшим понятием в регулярных выражениях. Существует несколько групп метасимволов.
Метасимволы - разделители строк
- ^ - начало строки
- $ - конец строки
- \A - начало текста
- \Z - конец текста
- . - любой символ в строке
Например:
- ^foobar - находит 'foobar' только если он в начале строки
- foobar$ - находит 'foobar' только если он в конце строки
- ^foobar$ - находит 'foobar' только если это единственное слово в строке
- foob.r - находит 'foobar', 'foobbr', 'foob1r' и т.д.
Метасимвол "^" по умолчанию совпадает только в начале входного текста, а метасимвол "$" - только в конце текста. Внутренние разделители строк, имеющиеся в тексте, не будут совпадать с "^" и "$". Однако, если Вам необходимо работать с текстом как с многострочным, чтобы "^" совпадал после каждого разделителя строки внутри текста, а "$" - перед каждым разделителем, то Вы можете включить модификатор /m. (см ниже)
Метасимволы \A и \Z аналогичны "^'' и "$'', но на них не действует модификатор /m, т.е. они всегда совпадают только с началом и концом всего входного текста.
Метасимвол "." по умолчанию совпадает с любым символом, однако, если Вы выключите модификатор /s, то "." не будет совпадать с разделителями строк.
"^" совпадает с началом входного текста, а также, если включен модификатор /m, с точкой непосредственно следующей после \x0D\x0A, \x0A или \x0D. Обратите внимание, что он не совпадает в промежутке внутри последовательности \x0D\x0A.
"$" совпадает с концом входного текста, а также, если включен модификатор /m, с точкой непосредственно предшествующей \x0D\x0A, \x0A или \x0D. Обратите внимание, что он не совпадает в промежутке внутри последовательности \x0D\x0A.
"." совпадает с любым символом, но если выключен модификаторr /s, то "." не совпадает с \x0D\x0A и \x0A и \x0D.
Обратите внимание, что "^.*$" (шаблон для пустой строки) не совпадает с пустой строкой вида \x0D\x0A, но совпадает с \x0A\x0D.
Метасимволы - стандартные перечни символов
- \w - буквенно-цифровой символ или "_"
- \W - не \w
- \d - цифровой символ
- \D - не \d
- \s - любой "пробельный" символ (по умолчанию - [ \t\n\r\f])
- \S - не \s
Стандартные перечни \w, \d и \s можно использовать и внутри перечней символов.
Например:
- foob\dr - находит 'foob1r', ''foob6r' и т.д. но не 'foobar', 'foobbr' и т.д.
- foob[\w\s]r - находит 'foobar', 'foob r', 'foobbr' и т.д. но не 'foob1r', 'foob=r' и т.д.
Метасимволы - границы слов
- \b - Совпадает на границе слова
- \B - Совпадает не на границе слова
Граница слова (\b) это точка между двумя символами, один из которых удовлетворяет \w, а другой - \W (в любом порядке), при этом перед началом и после конца строки подразумевается \W.
Метасимволы - повторения
После любого элемента регулярного выражения может следовать очень важный тип метасимвола - повторитель. Используя их Вы можете определить число допустимых повторений предшествующего символа, метасимвола или подвыражения.
- * - ноль или более раз ("жадный"), то же что {0,}
- + - один или более раз ("жадный"), то же что {1,}
- ? - ноль или один раз ("жадный"), то же что {0,1}
- {n} - точно n раз ("жадный")
- {n,} - не менее n раз ("жадный")
- {n,m} - не менее n но не более m раз ("жадный")
- *? - ноль или более раз ("не жадный"), то же что {0,}?
- +? - один или более раз ("не жадный"), то же что {1,}?
- ?? - ноль или один раз ("не жадный"), то же что {0,1}?
- {n}? - точно n раз ("не жадный")
- {n,}? - не менее n раз ("не жадный")
- {n,m}? - не менее n но не более m раз ("не жадный")
Т.о. {n,m} задает минимум n повторов и максимум - m. Повторитель {n} эквивалентен {n,n} и задает точно n повторов. Повторитель {n,} задает минимум n повторов. Теоретически величина параметров n и m не ограничена, но рекомендуется не задавать большие значения, поскольку в некоторых ситуациях это может потребовать существенных затрат времени и ОЗУ при обработке такого повторителя в связи с рекурсивным характером работы.
Если фигурные скобки встречаются в "неправильном" месте, где они не могут быть восприняты как повторитель, то они вопринимаются просто как символы.
Например:
- foob.*r - находит 'foobar', 'foobalkjdflkj9r' и 'foobr'
- foob.+r - находит 'foobar', 'foobalkjdflkj9r' но не 'foobr'
- foob.?r - находит 'foobar', 'foobbr' и 'foobr' но не 'foobalkj9r'
- fooba{2}r - находит 'foobaar'
- fooba{2,}r - находит 'foobaar', 'foobaaar', 'foobaaaar' и т.д.
- fooba{2,3}r - находит 'foobaar', или 'foobaaar' но не 'foobaaaar'
Небольшое пояснение по поводу "жадности". "Жадные" варианты повторителей пытаются захватить как можно большую часть входного текста, в то время как "не жадные" - как можно меньшую.
Например: "b+" как и "b*" примененные к входной строке "abbbbc" найдут "bbbb", в то время как "b+?" найдет только "b", а "b*?" - вообще - пустую строку; "b{2,3}?" найдет "bb", в то время как "b{2,3}" найдет "bbb".
Вы можете переключить все повторители в выражении в "не жадный" режим, воспользовавшись модификатором /g.
Метасимволы - варианты
Вы можете определить перечень вариантов, используя метасимвол "|" для их разделения, например "fee|fie|foe" найдет "fee'' или "fie'' или "foe'', (так же как "f(e|i|o)e"). В качестве первого варианта воспринимается все от предыдущего метасимвола "(" или "[" или от начала выражения до первого метасимвола "|", в качестве последнего - все от последнего "|" до конца выражения или до ближайшего метасимвола ")". Обычно, чтобы не запутаться, набор вариантов всегда заключают в скобки, даже если без этого можно было бы обойтись.
Варианты пробуются начиная с первого и попытки завершаются сразу же как удастся подобрать такой при котором совпадет вся последующая часть выражения. Это означает, что варианты не обязательно обеспечат "жадное" поведение. Например, если применить выражение "foo|foot" ко входной строке "barefoot", то будет найдено "foo'' так это первый вариант который позволил совпасть всему выражению.
Обратите внимание, что метасимвол "|" воспринимается как обычный символ внутри перечней символов, например, [fee|fie|foe] означает ровно то же самое что и [feio|].
Например:
- foo(bar|foo) - находит "foobar" или "foofoo".
Метасимволы - подвыражения
Метасимволы ( ... ) могут также использоваться для задания подвыражений.
Например:
- (foobar){8,10} - находит строку содержащую 8, 9 или 10 копий "foobar"
- foob([0-9]|a+)r - находит "foob0r", "foob1r" , "foobar", "foobaar" и т.д.
Метасимволы - обратные ссылки
Метасимволы от \1 до \9 воспринимаются как обратные ссылки. \<n> совпадает с ранее найденным подвыражением #<n>.
Например:
- (.)\1+ - находит "aaaa" и "cc"
- (.+)\1+ - также находит "abab" и "123123"
- (['"]?)(\d+)\1 - находит "13" (в дв.кавычках), или '4' (в один.кавычках) или 77 (без кавычек) и т.д.
Модификаторы
Модификаторы служат для изменения режимов работы.
Любой модификатор может меняться с помощью специальной конструкции (?...) внутри регулярного выражения.
#i
Регистро-независимый режим (по умолчанию использует выбранный в ОС язык по умолчанию)
#m
Воспринимать входной текст как многострочный, при этом метасимволы "^'' и "$'' будут совпадать не только в начале и конце текста в целом, но и в начале и в конце всех имеющихся в тексте строк
#s
Воспринимать входной текст как одну строку. При этом метасимвол ".'' совпадает с любым символом, если же этот модификатор выключен, то он не совпадает с разделителями строк.
#g
Выключая его Вы переключаете все повторители в "не жадный" режим (по умолчанию этот модификатор включен). Т.е. если его отключить, то все '+' работают как '+?', '*' как '*?' и т.д.
#r
Не стандартный модификатор. Если включен, то диапазоны вида а-я включают также букву 'ё', А-Я включают 'Ё', а а-Я включает вообще все русские буквы.
#(?imsxr-imsxr)
Позволяет изменять значения модификаторов
Например:
- (?i)Saint-Petersburg - находит 'Saint-petersburg' и 'Saint-Petersburg'
- (?i)Saint-(?-i)Petersburg - находит 'Saint-Petersburg' но не 'Saint-petersburg'
- (?i)(Saint-)?Petersburg - находит 'Saint-petersburg' и 'saint-petersburg'
- ((?i)Saint-)?Petersburg - находит 'saint-Petersburg', но не 'saint-petersburg'
|