Double Commander использует свободную Delphi-библиотеку TRegExpr Андрея В. Сорокина: http://www.regexpstudio.com/. Большинство из приведённых далее объяснений и примеров позаимствовано из справочного файла к этой библиотеке.
Регулярные выражения — это широко используемый способ описания шаблонов для поиска текста и проверки соответствия текста шаблону.
Специальные метасимволы позволяют определять, например, что мы ищем подстроку в начале входной строки или n повторений определённого символа.
Регулярные выражения предназначены главным образом для профессионалов, однако могут быть полезны и при работе в офисе для поиска определённых документов (см. примеры ниже).
Double Commander поддерживает регулярные выражения в следующих функциях:
Любой символ совпадает с самим собой, если он не относится к специальным метасимволам, описанным чуть ниже.
Последовательность символов совпадает с такой же последовательностью во входной строке, так что шаблон "bluh" совпадет с подстрокой "bluh" во входной строке.
Если необходимо, чтобы метасимволы или escape-последовательности воспринимались как обычные символы, их нужно предварять символом "\" ("экранировать"), например, метасимвол "^" обычно совпадает с началом строк, однако, если записать его как "\^", то он будет совпадать с символом "^", "\\" совпадает с "\" и т.д.
Примеры:
Примеры простого сравнения | |
---|---|
Выражение | Результат |
foobar |
находит "foobar" |
\^FooBarPtr |
находит "^FooBarPtr" |
Любой символ может быть определён с помощью escape-последовательности так же, как это делается в языках C или Perl: "\n" означает начало строки, "\t" — табуляцию и т.д.
\xnn, где nn — это последовательность шестнадцатеричных цифр, означает символ с ASCII-кодом nn.
Если необходимо определить двухбайтный (Unicode) символ, используем формат "\x{nnnn}", где "nnnn" — одна или более шестнадцатеричных цифр.
Escape-последовательности | |
---|---|
Выражение | Результат |
\xnn |
символ с шестнадцатеричным кодом nn |
\x{nnnn} |
символ с шестнадцатеричным кодом nnnn (один байт для обычного текста и два для Unicode) |
\t |
табуляция (HT/TAB), можно также \x09 |
\n |
новая строка (NL/LF), можно также \x0a |
\r |
возврат каретки (CR), можно также \x0d |
\f |
перевод страницы (FF), можно также \x0c |
\a |
звонок (BEL), можно также \x07 |
\e |
escape (ESC), можно также \x1b |
Примеры:
Примеры с escape-последовательностями | |
---|---|
Выражение | Результат |
foo\x20bar |
находит "foo bar" (обратите внимание на пробел посередине) |
\tfoobar |
находит табуляцию и "foobar" |
Вы можете определить набор, заключив символы в []. Набор будет совпадать с любым одним символов из перечисленных в нём.
Если первым символом набора (сразу после "[") идёт "^", то такой набор совпадает с любым символом не перечисленным в наборе.
Внутри набора символ "-" может быть использован для определения диапазона символов, например, 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" |
Примеры:
Примеры с наборами символов | |
---|---|
Выражение | Результат |
foob[aeiou]r |
находит "foobar", "foober" и т.д., но не "foobbr", "foobcr" и т.д. |
foob[^aeiou]r |
находит "foobbr", "foobcr" и т.д., но не "foobar", "foober" и т.д. |
Метасимволы — это специальные символы, являющиеся важнейшим понятием в регулярных выражениях.
Существует несколько типов метасимволов.
Выражения, помогающие указать разделители строк.
Разделители строк | |
---|---|
Выражение | Результат |
^ |
начало строки |
$ |
конец строки |
\A |
начало текста |
\Z |
конец текста |
. |
любой символ в строке |
Несколько примеров:
Примеры с разделителями строк | |
---|---|
Выражение | Результат |
^foobar |
находит "foobar" только в начале строки |
foobar$ |
находит "foobar" только в конце строки |
^foobar$ |
находит "foobar" только если это единственное слово в строке |
foob.r |
находит "foobar", "foobbr", "foob1r" и т.д. |
Метасимвол "^" по умолчанию совпадает только с началом входного текста, а метасимвол "$" — только с концом текста. Внутренние разделители строк, имеющиеся в тексте, не будут совпадать с "^" и "$".
Однако, если вам необходимо работать с текстом как с многострочным, чтобы "^" совпадал после каждого разделителя строки внутри текста, а "$" — перед каждым разделителем, то вы можете включить модификатор m.
Метасимволы \A и \Z аналогичны "^" и "$", но на них не действует модификатор m, т.е. они всегда совпадают только с началом и концом всего входного текста.
Метасимвол "." по умолчанию совпадает с любым символом, однако, если вы выключите модификатор s, то "." не будет совпадать с разделителями строк.
TRegExpr интерпретирует разделители строк так, как это рекомендовано на www.unicode.org в Technical Standard #18:
"^" совпадает с началом входного текста, а также, если включен модификатор m, с точкой, непосредственно следующей после \x0D\x0A, \x0A или \x0D (если вы используете Unicode-версию TRegExpr, то также \x2028, \x2029, \x0B, \x0C или \x85). Обратите внимание, что он не совпадает в промежутке внутри последовательности \x0D\x0A.
"$" совпадает с концом входного текста, а также, если включен модификатор m, с точкой, непосредственно предшествующей \x0D\x0A, \x0A или \x0D (если вы используете Unicode-версию TRegExpr, то также \x2028, \x2029, \x0B, \x0C или \x85). Обратите внимание, что он не совпадает в промежутке внутри последовательности \x0D\x0A.
"." совпадает с любым символом, но если выключен модификатор s, то "." не совпадает с \x0D\x0A, \x0A и \x0D (если вы используете Unicode-версию TRegExpr, то не совпадает также с \x2028, \x2029, \x0B, \x0C и \x85).
Обратите внимание, что "^.*$" (шаблон для пустой строки) не совпадает с пустой строкой вида \x0D\x0A, но совпадает с \x0A\x0D.
Выражения, помогающие указать наборы символов.
Наборы символов | |
---|---|
Выражение | Результат |
\w |
буквенно-цифровой символ или "_", т.е. [A-Za-z0-9_] |
\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" и т.д., но не "foob=r" и т.д. |
Граница слова (\b) — позиция между двумя символами, один из которых удовлетворяет \w, а другой — \W (в любом порядке), при этом перед началом и после конца строки подразумевается \W.
Границы слов | |
---|---|
Выражение | Результат |
\b |
совпадает на границе слов |
\B |
совпадает не на границе слов |
После любого элемента регулярного выражения может следовать очень важный тип метасимвола — повторитель (квантификатор).
Используя их, вы можете определить число допустимых повторений предшествующего символа, метасимвола или подвыражения.
Повторители | |
---|---|
Выражение | Результат |
* |
ноль или более раз ("жадный"), то же, что и {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" |
Метасимволы ( ... ) могут также использоваться для определения подвыражений — по завершении поиска выражения вы можете обратиться к любому подвыражению, а также подставлять подвыражения как маску.
Подвыражения нумеруются слева направо, в порядке появления открывающих круглых скобок.
Первое подвыражение имеет номер "1", поддерживается до 90 подвыражений (выражение в целом — "0", к нему можно обращаться как "$0" или "$&").
Примеры:
Подвыражения | |
---|---|
Выражение | Результат |
(foobar){8,10} |
находит строку, содержащую 8, 9 или 10 копий "foobar" |
foob([0-9]|a+)r |
находит "foob0r", "foob1r" , "foobar", "foobaar", "foobaar" и т.д. |
Примечания о шаблонах "Заменить на":
Пример:
Перевернём дату "21.01.2018" > "2018.01.21":
найти: (\d{2})\.(\d{2})\.(\d{4})
заменить: $3.$2.$1
Метасимволы от \1 до \9 интерпретируются как обратные ссылки. \n совпадает с ранее найденным подвыражением #n.
Несколько примеров:
Примеры обратных ссылок | |
---|---|
Выражение | Результат |
(.)\1+ |
находит "aaaa" и "cc" |
(.+)\1+ |
также находит "abab" и "123123" |
(['"]?)(\d+)\1 |
находит "13" (в двойных кавычках), или '4' (в одинарных кавычках) или 77 (без кавычек) и т.д. |
(?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" |
Модификатор x заставляет игнорировать пробелы, табуляции и разделители строк, что позволяет форматировать текст выражения.
Кроме того, если встречается символ #, то все последующие символы до конца строки воспринимаются как комментарий, например:
( (abc) # комментарий 1 | # Вы можете использовать пробелы для форматирования выражения - TRegExpr игнорирует их (efg) # комментарий 2 )
Естественно, это означает, что если вам нужно вставить в выражение пробел, табуляцию, разделитель строки или #, то в расширенном (x) режиме это можно сделать предваряя их "\" или используя escape-последовательность \xnn (внутри наборов символов все эти символы воспринимаются как обычно).
В совокупности эти возможности значительно улучшают читаемость регулярных выражений.