Регулярные выражения в Ключ-Астром

Материал из Документация Ключ-АСТРОМ
Версия от 13:05, 22 августа 2024; IKuznetsov (обсуждение | вклад) (Новая страница: «Регулярные выражения очень эффективны, если вы хотите найти или извлечь определенный ша...»)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)

Регулярные выражения очень эффективны, если вы хотите найти или извлечь определенный шаблон в строке. Однако с большой силой приходит большая ответственность. Регулярные выражения могут привести к неожиданным результатам (lazy vs greedy matching) и они могут быстро стать ресурсоемкими (catastrophic backtracking и repeated capture groups).

Регулярные выражения также часто неправильно понимаются. Небольшое регулярное выражение может легко потреблять много вычислительной мощности при неправильном использовании. В качестве примера рассмотрим это регулярное выражение (.*)+b. Это выражение может не выглядеть опасным, но если вы выполните его для большей строки, которая не содержит b, это выражение приведет к циклу, который будет длиться более 10 секунд.

По этим причинам мы ограничили регулярные выражения в Ключ-АСТРОМ. Однако почти во всех случаях это не ограничит вашу функциональность. Это может заставить вас узнать немного больше о регулярных выражениях.

Ограничения

Ознакомьтесь с приведенными ниже ограничениями, чтобы понять, как использовать регулярные выражения в контексте Ключ-АСТРОМ.

Количественные или повторяющиеся группы не допускаются

Количественные группы обычно не нужны, и поскольку они могут легко выйти из-под контроля, мы их не допускаем. Чтобы лучше понять это, перейдите на https://regex101.com и оцените следующее регулярное выражение:

Regex: (a+)+b

Value:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

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

Greedy matches в группах против possessive matches

Ключ-АСТРОМ не допускает Greedy matches в группах. Вместо этого используйте lazy или possessive matches.

Прототипом регулярного выражения является термин .*. Greedy match определяется как Совпадения от нуля до неограниченного количества раз, столько раз, сколько возможно, возвращая обратно по мере необходимости (Greedy). Проблема здесь в столько раз и возвращении обратно. Люди обычно используют это для сопоставления чего-либо, пока не будет выполнено граничное условие. Рассмотрим следующее сопоставление регулярного выражения:

Regex: key: (.*);

Value: something. key: value; something else

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

Лучший способ сделать это следующий:

Regex: key: ([^;]*+)

Value: something. key: value; something else

Это соответствие будет соответствовать до тех пор, пока не будет найдено ; после key: . Плюс также превращает это в possessive match, определяемое как: Совпадает от нуля до неограниченного количества раз, столько раз, сколько возможно, без возврата (possessive). Ключевым моментом здесь является то, что он не возвращается. Другими словами, как только что-то совпало, движок не будет пересматривать и не будет смотреть назад, а только вперед. Именно поэтому нам нужно уточнить соответствие от «все» (.) до «все, но не ;». Нам нужно сказать ему, чтобы он соответствовал всему, но не ;.

Если сравнить первое регулярное выражение против второго в отладчике регулярных выражений (перейдите по двум ссылкам) вы также заметите, что первый занимает 42 шага, а второй — 9! Вот почему мы рекомендуем вам использовать possessive matches в целом.

Группы не допускаются для простых матчей.

Группы захвата в регулярных выражениях используются для извлечения информации. Иногда эта концепция неправильно используется для простых совпадений поиска. Поскольку это только добавляет накладные расходы и не является необходимым, Ключ-АСТРОМ не допускает этого. В большинстве случаев можно использовать атомарные группы вместо этого. Для обеспечения высокой производительности продукта в определениях регулярных выражений могут применяться дополнительные ограничения группировки, например, в правилах именования запросов .

Ключ-АСТРОМ допускает только одну группу захвата в местах, где вам нужно извлечь значение. Логика здесь такова: если регулярное выражение содержит группу, Ключ-АСТРОМ будет ее использовать. В противном случае для извлечения используется полное совпадение.

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

Если вы хотите, например, получить версию Windows из строки пользовательского агента, вы можете использовать следующее регулярное выражение:

Regex: Windows NT[^)]+

Value: Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0 Safari/537.36

Это позволит захватить данные Windows NT 10.0, и в группе захвата нет необходимости.

Ключ-АСТРОМ не допускает обратных ссылок

Обратные ссылки часто используются для решения иерархических или рекурсивных соответствий, оба из которых с большой вероятностью могут оказаться очень затратными и не нужны в Ключ-АСТРОМ.

Другие распространенные заблуждения

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

Regex: .*key: [^;]*+.*

Value: something. key: value; something else

Это соответствует полной строке, а не только тому, что нужно. Это основано на недоразумении, что заданное регулярное выражение всегда будет соответствовать полному тексту, тогда как обычно оно используется для поиска подстроки. В Ключ-АСТРОМ условия регулярного выражения обычно ищут шаблон и не сопоставляют принудительно весь ввод. Начальные и конечные (.*) соответствия не нужны, поэтому, пожалуйста, не используйте их.