&Anders.Lund; &Anders.Lund.mail;
Андрей
Балагута

    uj2@mail.ru

Перевод на русский

# Регулярные выражения

    Это приложение содержит краткое, но, надеюсь, достаточно ясное введение в мир регулярных выражений. Здесь описаны регулярные выражения в той форме, в которой они используются в &kate;; к сожалению, они не совместимы с с регулярными выражениями perl и grep.

## Введение

Регулярные выражения - это средство, позволяющее описывать содержание строк в некотором формализованном виде, что даёт возможность приложениям определять принадлежность той или иной строки определённому формату. В дополнение ко всему некоторые приложения могут сохранять части совпавшей строки для их последующего использования.

Приведём небольшой пример. Допустим, вы хотите найти в тексте все абзацы, которые начинаются с фамилий Петров или Иванов, за которыми следует любая форма глагола рассказывать (для чистоты эксперимента возьмём всего две формы рассказал и рассказывал).

С помощью обычного поиска вам бы понадобилось сначала найти фамилию Петров, возможно, дополненную буквами рассказ, что-то вроде этого: `Петров рассказ`. При поиске совпадений пришлось бы пропускать все те строки, что стоят не в начале абзаца. После этого последовал бы повторный поиск для второй фамилии...

Регулярные выражения позволяют произвести такую операцию поиска за один раз, причём с гораздо большей точностью.

Регулярные выражения содержат правила, позволяющие точно выразить вид строки для поиска. Наш пример можно выразить словесно: Строка, начинающаяся со слов Петров или Иванов, перед которыми могут стоять до четырёх пробелов или символов табуляции, после фамилии должен стоять пробел, за пробелом - рассказ, после чего может (необязательно!) стоять суффикс ыв, и, наконец, суффикс ал. Посмотрите, как это можно записать в форме регулярного выражения:

`^[ \t]{0,4}(Петров|Иванов) рассказ(ыв)?ал`

Этот пример демонстрирует четыре основных понятия современных регулярных выражений:

- Шаблоны

- Утверждения

- Кванторы

- Обратные ссылки

Значок `^`, с которого начинается выражение - это утверждение, которое подтверждает совпадение только в том случае, если совпавшая цепочка символов начинается с новой строки.

`[ \t]` и `(Петров|Иванов) рассказ(ыв)?ал` - это шаблоны. Первый представляет собой символьный класс, который совпадает либо с пробелом, либо с символом табуляции. Второй содержит вложенный шаблон, совпадающий со словами `Петров` или `Иванов`, затем идёт проверка на точное совпадение со строкой `рассказ`, потом ещё один вложенный шаблон, который определяет вхождение символов `ыв`, и, в самом конце, проверка на точное совпадение с символами `ал`

Строка `{0,4}` и символ вопроса после вложенного шаблона `(ыв)` - это кванторы. Первый можно трактовать следующим образом: возможен повтор предыдущего символа от 0 до 4 раз. Второй квантор действует аналогично, позволяя повторить стоящий перед ним вложенный шаблон 0 или 1 раз.

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

Как вы могли убедиться на предыдущем примере, регулярные выражения - это очень эффективное средство поиска, позволяющее найти именно то, что вам нужно, без особых усилий.

В следующих разделах подробно рассмотрены шаблоны, символьные классы, утверждения, кванторы и обратные ссылки. В конце этой главы вы найдёте несколько полезных примеров.

## Шаблоны

Шаблоны состоят из символов и символьных классов. Допускается вложенность, в этом случае вложенные шаблоны заключаются в круглые скобки.

### Управляющие последовательности

И в шаблонах, и в символьных классах некоторые символы имеют специальное значение. Если вы хотите использовать эти символы при поиске именно как символы, нужно записать их определенным образом, чтобы анализатор регулярных выражений считал их обычными литералами.

Делается это очень просто, нужно всего лишь поставить перед таким символом бэк-слеш (`\`).

Анализатор регулярных выражений игнорирует обратную черту перед символами, которые не имеют специального значения в контексте; например, если вы вместо обычного символа j напишете `\j`, анализатор его воспримет просто как j. Таким образом, если вы не уверены, имеет ли символ специальное значение, можете спокойно ставить перед ним бэк-слеш.

Чтобы использовать обратную черту в качестве литерала, продублируйте его: `\\`.

### Символьные классы и сокращения

Символьный класс - это выражение, которое позволяет проверить один символ на принадлежность определенному набору символов. Чтобы использовать его в регулярных выражениях, нужно в квадратных скобках записать все верные символы или сокращенные классы, описанные ниже.

Простые символьные классы содержат один или несколько символов, например, `[abc]` (проверка на любой из символов a, b или c) или `[0123456789]` (проверка на любую цифру).

Поскольку буквы и цифры логически упорядоченны, вы можете сокращать классы, используя диапазоны: `[a-c]` аналогично `[abc]`, `[0-9]` аналогично `[0123456789]`. Можно комбинировать диапазоны с обычным перечислением символов: `[a-fynot1-38]` (проверка на любой из символов a,b,c,d, e,f,y,n,o,t, 1,2,3 или 8).

Чтобы проверить символ без учета регистра в любом случае (регулярное выражение может учитывать или не учитывать регистр символов), нужно написать примерно следующее: `[aAbB]`.

Можно создать исключающий класс, который проверяет символ на не-вхождение в заданный набор символов. Обычный символьный класс превращается в исключающий добавлением символа `^` перед набором символов:

`[^abc]` - проверка на любой символ, кроме a, b и c.

В дополнение к обычным литералам можно использовать следующие сокращения:

`\a`

  Проверка на ASCII-символ звонка (BEL, 0x07).

`\f`

  Проверка на ASCII-символ перевода страницы (FF, 0x0C).

`\n`

  Проверка на символ перевода строки (LF, 0x0A, символ перехода на новую строку в Unix).

`\r`

  Проверка на символ возврата каретки (CR, 0x0D).

`\t`

  Проверка на символ горизонтальной табуляции (HT, 0x09)

`\v`

  Проверка на символ вертикальной табуляции (VT, 0x0B).

`\xhhhh`

  Проверка на символ в кодировке Unicode, соответствующий номеру hhhh (в пределах 0x0000-0xFFFF). \0ooo (первый символ - ноль) - проверка на символ в кодировке ASCII/Latin-1, соответствующий восьмеричному номеру ooo (в пределах 0-0377).

`.` (точка)

  Проверка на любой символ (включая переход на новую строку).

`\d`

  Проверка на цифровой символ. Аналогично классу `[0-9]`.

`\D`

  Проверка на любой символ, не являющийся цифровым. Аналогично `[^0-9]` или `[^\d]`

`\s`

  Проверка на пробельный символ. Фактически аналогично классу `[ \t\n\r]`

`\S`

  Проверка на любой символ, не являющийся пробельным. Фактически равнозначно `[^ \t\r\n]` и аналогично `[^\s]`

`\w`

  Проверка на любой алфавитно-цифровой символ (как вы поняли, сюда включаются все буквы и цифры). Подчеркивание (`_`) не входит в этот класс, в отличие от регулярных выражений perl. Это сокращение аналогично классу `[a-zA-Z0-9]`

`\W`

  Проверка на любой символ, не являющийся алфавитно-цифровым. Аналогично классу `[^a-zA-Z0-9]` или `[^\w]`

Аббревиатурные классы можно помещать в обычные классы; например, чтобы выполнить проверку на алфавитно-цифровой символ, точку или пробел, вы можете написать так: `[\w \.]`

В текущей версии не поддерживается нотация классов POSIX (`[:<class name>:]`).

#### Символы со специальным значением в символьных классах

Ниже перечислены символы, имеющие специальное значение в определениях символьных классов ([]). Для использования в качестве обычных литералов они должны быть предварены бэк-слешем.

`]`

  Закрывает символьный класс. Этот символ должен быть предварен бэк-слешем, кроме тех случаев, когда стоит непосредственно в начале класса или сразу после символа `^`

`^`

  Если стоит в начале, объявляет исключающий класс. Чтобы использовать как литерал в начале класса, нужно поставить бэк-слеш, иначе слеш не нужен.

`-` (дефис)

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

`\` (обратная черта)

  Спецсимвол (escape character). Чтобы использовать как литерал, продублируйте.

### Альтернативы: проверка на один из нескольких шаблонов

Если вы хотите выполнить проверку на один (любой) шаблон из определенного набора, используйте альтернативы. Чтобы объявить альтернативу, нужно все шаблоны набора записать через пайп (`|`).

Например, чтобы найти любое из имён Вася и Петя, нужно использовать такое выражение: `Вася|Петя`.

### Вложенные шаблоны

Вложенными называются шаблоны, заключенные в круглые скобки. Они используются в разных целях:

#### Определение альтернатив

Используя вложенные шаблоны, вы можете группировать набор альтернатив внутри сложных шаблонов. Напомню, альтернативы разделяются символом пайп (|).

Например, чтобы найти одно из слов int, float или double, вы можете использовать шаблон `int|float|double`. Если же вы хотите найти одно из этих слов, за которым идут пробелы, а за ними какие-то символы, то вы должны оформить альтернативу как вложенный шаблон: `(int|float|double)\s+\w+`.

#### Захват совпавшего текста (обратные ссылки)

Чтобы создать обратную ссылку, оформите как вложенный шаблон ту часть выражения, которую нужно запомнить.

Например, если вы хотите найти два одинаковых слова, разделённых запятой и, возможно, пробелами, можно использовать такое выражение: `(\w+),\s*\1`. Вложенный шаблон `\w+` ищет цепочку алфавитно-цифровых символов, а всё выражение ищет ту же цепочку, за которой следует запятая, далее могут идти пробелы, а за ними точно такая же цепочка (строка `\1` ссылается на первый вложенный шаблон, заключенный в круглые скобки).

#### Просматривающие утверждения

Просматривающее утверждение - это вложенный шаблон, который начинается с символов `?=` или `?!`.

Например, чтобы найти слово Билл, за которым может следовать что угодно, кроме слова Гейтс, нужно составить такое выражение: `Билл(?! Гейтс)` (оно совпадет с Билл Клинтон, Билли хороший мальчик, но не с именем известного магната).

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

Смотрите также раздел Утверждения

### Символы со специальным значением в шаблонах

Следующие символы имеют специальное значение в шаблонах, поэтому, чтобы использовать их в качестве обычных символов, нужно впереди ставить обратную черту:

`\` (обратная черта)

  С него должны начинаться все спецсимволы.

`^`

  Проверка на начало строки.

`$`

  Проверка на конец строки.

`()` (левая и правая круглые скобки)

  Объявление вложенного шаблона.

`{}` (левая и правая фигурные скобки)

  Объявление числового квантора.

`[]` (левая и правая квадратные скобки)

  Объявление символьного класса.

`|` (вертикальная черта)

  Логическое ИЛИ. Используется для разделения альтернатив.

`+` (плюс)

  Квантор один или более.

`*` (звездочка)

  Квантор ноль или более.

`?` (знак вопроса)

  Необязательный символ. Можно считать его квантором ноль или один.

## Кванторы

Кванторы выполняют проверку на определенное количество повторений символа, шаблона или символьного класса.

Кванторы записываются в фигурных скобках (`{` и `}`). Общий вид квантора: `{[минимальное-количество-совпадений][,[максимальное-количество-совпадений]]}`

Использование кванторов лучше пояснить на примерах:

`{1}`

  Ровно одно появление

`{0,1}`

  Ноль или одно появление

`{,1}`

  То же самое, но набирать меньше ;)

`{5,10}`

  Как минимум 5 повторений, максимум - 10.

`{5,}`

  Как минимум 5 повторений (без верхней границы).

Также определены несколько сокращений:

`*` (звездочка)

  аналогично `{0,}`, найти любое количество повторений (вплоть до нуля повторений).

`+` (плюс)

  аналогично `{1,}`, как минимум одно появление.

`?` (знак вопроса)

  аналогично `{0,1}`, ноль или одно появление.

### Жадность

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

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

### Примеры использования

Здесь приведено несколько примеров использования кванторов.

`^\d{4,5}\s`

  Совпадет с 1234 вперед и 12345 стоп, но не совпадет ни с 567 восемь, ни с 223459 много.

`\s+`

  Проверка на один или более пробельных символов.

`(ля){1,}`

  Совпадет с ляляля и с подстрокой ля в словах кляча и земля

`/?>`

  Совпадет с /> в <closeditem/>, а также с > в строке <openitem>.

## Утверждения

Утверждения накладывают дополнительные условия на проверку регулярного выражения.

Утверждение не проверяет символы, скорее, оно анализирует совпавшую строку перед тем как подтвердить совпадение. Например, утверждение граница слова не пытается найти символ-разделитель слов, наоборот, оно проверяет, что в данной позиции нет алфавитно-цифрового символа. Это означает, что утверждение будет верно даже в случае отсутствия символа-разделителя, например, в конце строки поиска.

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

Регулярные выражения, описанные в этом руководстве, поддерживают следующие утверждения:

`^` (начало строки)

  Проверка на начало строки.

  Выражение `^Петр` совпадет с Петр в строке Петр, здравствуйте!, но не в строке Здравствуйте, Петр!.

`$` (конец строки)

  Проверка на конец строки поиска.

  Выражение `ты\?$` совпадет с последним ты в строке - Ты не сделаешь этого! - А ты?, но не совпадет ни с какой частью строки Ты не сделал этого, так?.

`\b` (граница слова)

  Проверяет, есть ли в данном месте с одной стороны алфавитно-цифровой символ, а с другой - не алфавитно-цифровой (необязательно разделитель!).

  Это утверждение используется для поиска границ слов; например, можно использовать два таких утверждения, чтобы найти целое слово. Выражение `\bиз\b` совпадет с отдельным словом из во фразе Он выпал из этого окна, хорошо хоть, что тут низко, но не совпадет с из в слове низко.

`\B` (нет границы слова)

  Действие этого утверждения обратно утверждению \b.

  Это значит, что данное утверждение будет совпадать, например, в середине слова: выражение `\Bце\B` совпадет с це в строке сцена, но не в целое.

`(?=ШАБЛОН)` (подтверждающий просмотр)

  Просматривающие утверждения действуют аналогично обычным шаблонам, с той лишь разницей, что текст, совпавший (или не совпавший, в зависимости от типа просмотра) с утверждением, не будет включен в результирующее совпадение. Подтверждающий просмотр проверяет текст на предмет совпадения с ШАБЛОНОМ утверждения.

  Выражение `программ(?=\w)` совпадет с программ в слове программист, но не во фразе Он написал много хороших программ!.

`(?!ШАБЛОН)` (отрицающий просмотр)

  Отрицающий просмотр проверяет текст на предмет несовпадения с ШАБЛОНОМ.

  Выражение `const \w+\b(?!\s*&)` совпадет с const char в строке const char* foo, но не совпадет с const QString в const QString& bar, поскольку & совпадает с шаблоном отрицающего просмотра.