м (IKuznetsov переименовал страницу Регулярные выражения в Ключ-Астром в Регулярные выражения в АппОптима) |
Нет описания правки |
||
| Строка 3: | Строка 3: | ||
Регулярные выражения также часто неправильно понимаются. Небольшое регулярное выражение может легко потреблять много вычислительной мощности при неправильном использовании. В качестве примера рассмотрим это регулярное выражение <code>(.*)+b</code>. Это выражение может не выглядеть опасным, но если вы выполните его для большей строки, которая не содержит <code>b</code>, это выражение приведет к циклу, который будет длиться более 10 секунд. | Регулярные выражения также часто неправильно понимаются. Небольшое регулярное выражение может легко потреблять много вычислительной мощности при неправильном использовании. В качестве примера рассмотрим это регулярное выражение <code>(.*)+b</code>. Это выражение может не выглядеть опасным, но если вы выполните его для большей строки, которая не содержит <code>b</code>, это выражение приведет к циклу, который будет длиться более 10 секунд. | ||
По этим причинам мы ограничили регулярные выражения в | По этим причинам мы ограничили регулярные выражения в АппОптима. Однако почти во всех случаях это не ограничит вашу функциональность. Это может заставить вас узнать немного больше о регулярных выражениях. | ||
== Ограничения == | == Ограничения == | ||
Ознакомьтесь с приведенными ниже ограничениями, чтобы понять, как использовать регулярные выражения в контексте | Ознакомьтесь с приведенными ниже ограничениями, чтобы понять, как использовать регулярные выражения в контексте АппОптима. | ||
=== Количественные или повторяющиеся группы не допускаются === | === Количественные или повторяющиеся группы не допускаются === | ||
| Строка 18: | Строка 18: | ||
=== Greedy matches в группах против possessive matches === | === Greedy matches в группах против possessive matches === | ||
АппОптима не допускает '''Greedy matches''' в группах. Вместо этого используйте '''lazy''' или '''possessive matches'''. | |||
Прототипом регулярного выражения является термин <code>.*</code>. '''Greedy match''' определяется как '''Совпадения от нуля до неограниченного количества раз, столько раз, сколько возможно, возвращая обратно по мере необходимости (Greedy)'''. Проблема здесь в '''''столько раз''''' и '''''возвращении обратно'''''. Люди обычно используют это для сопоставления чего-либо, пока не будет выполнено граничное условие. Рассмотрим следующее сопоставление регулярного выражения: | Прототипом регулярного выражения является термин <code>.*</code>. '''Greedy match''' определяется как '''Совпадения от нуля до неограниченного количества раз, столько раз, сколько возможно, возвращая обратно по мере необходимости (Greedy)'''. Проблема здесь в '''''столько раз''''' и '''''возвращении обратно'''''. Люди обычно используют это для сопоставления чего-либо, пока не будет выполнено граничное условие. Рассмотрим следующее сопоставление регулярного выражения: | ||
| Строка 39: | Строка 39: | ||
=== Группы не допускаются для простых матчей. === | === Группы не допускаются для простых матчей. === | ||
Группы захвата в регулярных выражениях используются для извлечения информации. Иногда эта концепция неправильно используется для простых совпадений поиска. Поскольку это только добавляет накладные расходы и не является необходимым, | Группы захвата в регулярных выражениях используются для извлечения информации. Иногда эта концепция неправильно используется для простых совпадений поиска. Поскольку это только добавляет накладные расходы и не является необходимым, АппОптима не допускает этого. В большинстве случаев можно использовать '''''[https://www.regular-expressions.info/atomic.html атомарные группы]''''' вместо этого. Для обеспечения высокой производительности продукта в определениях регулярных выражений могут применяться дополнительные ограничения группировки, например, '''''[[Настройка наименования запросов|в правилах именования запросов]]''''' . | ||
АппОптима допускает только одну группу захвата в местах, где вам нужно извлечь значение. Логика здесь такова: если регулярное выражение содержит группу, АппОптима будет ее использовать. В противном случае для извлечения используется полное совпадение. | |||
Это означает, что вам вообще не нужно использовать группы захвата. В большинстве сценариев извлечения достаточно просто определить, что вы хотите получить. В случае извлечения следующее регулярное выражение захватит значение — группа захвата не нужна. | Это означает, что вам вообще не нужно использовать группы захвата. В большинстве сценариев извлечения достаточно просто определить, что вы хотите получить. В случае извлечения следующее регулярное выражение захватит значение — группа захвата не нужна. | ||
| Строка 53: | Строка 53: | ||
Это позволит захватить данные <code>Windows NT 10.0</code>, и в группе захвата нет необходимости. | Это позволит захватить данные <code>Windows NT 10.0</code>, и в группе захвата нет необходимости. | ||
=== | === АппОптима не допускает обратных ссылок === | ||
Обратные ссылки часто используются для решения иерархических или рекурсивных соответствий, оба из которых с большой вероятностью могут оказаться очень затратными и не нужны в | Обратные ссылки часто используются для решения иерархических или рекурсивных соответствий, оба из которых с большой вероятностью могут оказаться очень затратными и не нужны в АппОптима. | ||
== Другие распространенные заблуждения == | == Другие распространенные заблуждения == | ||
| Строка 63: | Строка 63: | ||
<code>Value: something. key: value; something else</code> | <code>Value: something. key: value; something else</code> | ||
Это соответствует полной строке, а не только тому, что нужно. Это основано на недоразумении, что заданное регулярное выражение всегда будет соответствовать полному тексту, тогда как обычно оно используется для поиска подстроки. В | Это соответствует полной строке, а не только тому, что нужно. Это основано на недоразумении, что заданное регулярное выражение всегда будет соответствовать полному тексту, тогда как обычно оно используется для поиска подстроки. В АппОптима условия регулярного выражения обычно ищут шаблон и не сопоставляют принудительно весь ввод. Начальные и конечные (<code>.*</code>) соответствия не нужны, поэтому, пожалуйста, не используйте их. | ||
Текущая версия от 12:06, 22 декабря 2024
Регулярные выражения очень эффективны, если вы хотите найти или извлечь определенный шаблон в строке. Однако с большой силой приходит большая ответственность. Регулярные выражения могут привести к неожиданным результатам (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
Это соответствует полной строке, а не только тому, что нужно. Это основано на недоразумении, что заданное регулярное выражение всегда будет соответствовать полному тексту, тогда как обычно оно используется для поиска подстроки. В АппОптима условия регулярного выражения обычно ищут шаблон и не сопоставляют принудительно весь ввод. Начальные и конечные (.*) соответствия не нужны, поэтому, пожалуйста, не используйте их.