Если вы пишите прототип, или если скорость работы не принципиальна — используйте регулярные выражения. Это ускорит скорость разработки и уменьшит количество кода. Но, если итоговое решение будет работать медленно, то его всегда можно будет переписать без использования регулярных выражений.
- PCRE, применяется в PHP и др. ПО
- ECMA 262, применяется в JavaScript
- есть и другие достойные внимания, но в этом документе не рассматриваются
| Тип обработки | JavaScript | PHP |
|---|---|---|
| Проверка соответствия (валидация) | RegExp.test() |
preg_match(), preg_grep() |
| Поиск и захват подстрок | RegExp.exec(), String.match(), String.search() |
preg_match_all() |
| Поиск, захват и замена подстрок | String.replace() |
preg_replace(), preg_replace_callback(), preg_replace_callback_array(), preg_filter() |
| Поиск и разбиение на подстроки | String.split() |
preg_split() |
- Полное — вся строка соответствует шаблону регулярного выражения, которое всегда начинается с
^и заканчивается на$. - Частичное — часть строки соответствует шаблону регулярного выражения. Наличие символов
^и$опционально.
Полное соответствие обычно используют для валидации (проверки) строк на соответствие или не соответствие регулярному выражению. А частичное — для синтаксического анализа (парсинга) и лексического анализа (токенизации) строк.
Из частичного соответствия очень легко сделать полное, указав ^ в начале и $ в конце. В обратную сторону — сложнее, т.к. при необходимости необходимо явно указывать границы начала и конца искомой подстроки. Обычно это делают через (?<!…) и (?!…) соответственно.
Главная проблема медлительности — многочисленные откаты в случае неудачи в одной из веток поиска, которые могут привести к превышению максимального времени выполнения. Подробнее см. Catastrophic Backtracking.
- Пример долго выполняющегося регулярного выражения PCRE и его оптимизированной версии, работающей почти в 10 раз быстрее: PCRE
- Используйте атомарную группировку
(?>…)и/или однократные квантификаторы:…?+,…*+,…++. В диалекте JS нет такой встроенной возможности, но можно использовать конструкцию типа(?=(…))\1, которая является аналогом. - Не используйте вложенные циклы типа
(…+)+. Используйте конструкции типа(?!…)(…)+,(?=…)(…)+,(…)+(?<!…),(…)+(?<=…). - В случае отсутствия
^задавайте явно границу начала совпадения через\bили(?<!…). В случае отсутствия$задавайте явно границу совпадения через\bили(?!…). - Замените нежадные квантификаторы типа
.*?на жадные. Но часть рег. выражения нужно будет немного переписать и усложнить для увеличения скорости. - Не используйте флаг
/u(юникод в PCRE). Возможно, часть рег. выражения нужно будет немного переписать и усложнить для увеличения скорости.
- Регулярные выражения PCRE пока поддерживают просмотр назад только с фиксированной длиной. Т.е. внутри
(?<!…)нельзя использовать квантификаторы?,*,+,{…,…}. Но есть способ обойти это ограничение, используя\K. - Регулярные выражения JS пока не поддерживают всех возможностей PCRE, но есть готовые решения:
- Библиотека
XRegExp, которая расширяет стандартные возможности рег. выражений в JS до уровня PCRE. String.prototype.matchRecursive()— реализация JavaScript методаString.match()с учётом рекурсии: JS Fiddle- Генератор регулярного выражения до заданной глубины рекурсии
(?R)(TODO сделать форму ввода): JS Fiddle
- Библиотека
Используйте сервис regex101.com для написания и тестирования ваших регурярных выражений, а так же для поиска и замены подстрок через регулярные выражения в диалектах PRCE, JS, Python, Golang.
Каждое регулярное выражение написано так, чтобы оно
- работало максимально быстро (по советам выше)
- было читабельным с выделением логических частей (используется флаг
/x) и описанием в комментариях (#)
- Целые:
/^[-−]? (?:[1-9]\d*|0) $/sx - Целые и десятичные:
/^[-−]? (?:[1-9]\d*|0) (?:\.\d+)? $/sx - Денежный формат:
/^[-−]? (?:[1-9]\d*|0) (?:\.\d{1,2})? $/sx - Число с разделением тысячных через запятую и десятичными: PCRE
- Дата в формате
ГГГГ-ММ-ДД:/^\d{4}-\d{2}-\d{2}$/sSX - Время в формате
ЧЧ:ММ:СС:/^\d{2}:\d{2}(:\d{2})?$/sSX
- Валидация даты в формате
ГГГГ-ММ-ДДс проверкой корректности года, месяца и дня, но без проверки YYYY-02-29 в високосных годах (нужно доделать): PCRE
- Валидация IPv4 + IPv6: PCRE, link. В языках программирования есть готовый валидатор: PHP —
filter_var(), NodeJS —net.isIP(). - Захват адреса электронной почты (Email address) из текста: PCRE
- Захват многострочных комментариев, где они НЕ могут быть вложены друг в друга (C-style), в 3 раза эффективнее, чем
/\* .*? \*/: PCRE - Захват многострочных комментариев, где они могут быть вложены друг в друга (PostgreSql): PCRE
- Base64: PCRE
Включая номера, которые пытаются скрыть, используя разные разделители цифр.
PCRE
/
(?<!\d) #boundary
( #1 код страны для РФ
\+7 [^\d\n,;]{0,5}
| [78] [^\d\n,;]{0,5}
)?
(?<!\+)
([489][\dOО]{2}) #2 код города или код мобильного оператора для РФ (цифра, поддельная русская/англ. буква, похожая на ноль)
( (?:(?!\x20*[дД][оО]\x20*\d) #не является диапазоном
(?!\x20*р(?:уб)?[^а-я]) #не является денежной суммой
[^\d\n,;]{0,5}
[\dOО]
){7}
) #3 номер телефона для РФ 7 цифр
(?!@[a-zA-Zа-яёА-ЯЁ\d]+\.) #не является частью email
(?!\x20*(?:руб|р\.|года)) #не является частью денежной суммы или указанием года
(?!\d) #boundary
/gxsТестирование
# Invalid
79261234567@mail.ru
79261234567@почта.москва
+7926123456
+7 926123456
+7 926 123456
+7(926)123456
+9261234567
# Valid
## РФ fake
9261234567
79261234567
8 916 123 тире 45 тире 67
8_916_123_45_67
## РФ regular
++79261234567
+79261234567
+7 9261234567
+7 926 1234567
+7 968 123-45-67
+7(965)123-45-67 (доб. 318)
+7 965 123 45 67 #221
+7 965 123 45 67+221
+7 (495) 361-999-1
+7 (83166) 1-23-45
+7 831 66 1-23-45
## РФ local:
89261234567
8(965)1234567 c 10 до 24
8(965)123 45 67 (с 11.00 до 20.00)
8 965 66-38-5-85 (с 12:00 до 18:00)
8-965-663-85-85 (from 10am to 18pm)
8 (495) 361-999-1 (from 8 AM to 9 PM)
8 8316 123 4 56
## UAE:
+971 2 4567890
+971 (0)2 4567890
+971 4 123 45 67
+971-4-1234567
+971-50-1234567
+971-50-123-45-67
## Germany:
+49 511 4735138
+49 511 473-51-38
+49(511)473-51-38
+49 (511) 473-51-38
## Argentina
+54 9 2982 123456
## Moldova
+373 68 007777
+373 68 007777
- Захват xml и html сущностей: PCRE, JS (strict); PCRE (non strict). См. так же список именованных сущностей в JSON.
- Захват заданных html тегов с учётом их парности без вложенных таких же тегов: PCRE, JS
- Захват заданных html тегов с учётом их парности и вложенности друг в друга (рекурсивно): PCRE, JS
- Вставляет теги
</li>там, где они пропущены (чинит некорректную вложенность тегов<li>): PCRE
- Удаление начальных и конечных пробелов: PCRE
- Валидация слова на английском языке во множественном числе: PCRE
- Валидация ФИО на русском или английском языке: PCRE
- Выделение слов и чисел из текста PCRE
- Поиск дубликатов в списке через запятую PCRE
- Детектирование SQL на модификацию данных: PCRE
- Разбиение SQL на несколько запросов по символу
;: PCRE
Захват квотированной строки (PCRE):
(?>
'(?>[^']+|'')*' #string constants
| \b[Ee]'(?>[^\\']+|''|\\.)*' #string constants with C-style escapes
| (?<stringDollarTag>\$[a-zA-Z\d_]*\$) #dollar-quoted string
[^$]*+ #speed improves
.*?
\k<stringDollarTag>
)Захват квотированного названия объекта БД (PCRE):
"(?>[^"]+|"")*"Захват комментариев (PCRE):
(?>
#singe-line comment
(?<singeLineComment>-- [^\r\n]*+)
|
#multi-line comment
(?<MutilineComment>
/\*
[^*/]*+
(?> [^*/]++
| \*[^/]
| /[^*]
| (?&MutilineComment) #recursive
)*+
\*/
)
)Захват квотированной строки (PCRE):
(?>"(?>[^\\"]+|""|\\.)*"|'(?>[^\\']+|''|\\.)*')Захват квотированного названия объекта БД (PCRE):
`(?>[^\\`]+|``|\\.)*`Захват комментариев (PCRE):
(?>
#singe-line comment
(?<singeLineComment>-- (?=\s) [^\r\n]*+)
|
#multi-line comment by Jeffrey Friedl (fastest)
(?<multiLineComment>
/\*
[^*]* \*+
(?:[^*/][^*]*\*+)*
/
)
)Захват квотированной строки (PCRE):
'(?>[^\\']+|''|\\.)*'Захват квотированного названия объекта БД (PCRE):
(?>"(?>[^\\"]+|""|\\.)*"|`(?>[^\\`]+|``|\\.)*`)Захват комментариев (PCRE):
(?>
#singe-line comment
-- [^\r\n]*+
|
#multi-line comment by Jeffrey Friedl (fastest)
/\*
[^*]* \*+
(?:[^*/][^*]*\*+)*
/
)- Валидация (неполная, но быстрая) регулярного выражения на диалект ECMA 262 (JavaScript), есть проверка на уникальность флагов: PCRE
Регулярное выражение: PCRE
Пароль должен соответствовать следующим требованиям:
- длина от 8 до 72 символов (72 символа — это ограничение алгоритма bf)
- допускаются только цифры, английские буквы и знаки пунктуации
- содержит хотябы одну цифру (0-9)
- содержит хотябы одну английскую прописную букву (A-Z)
- содержит хотябы одну английскую строчную букву (a-z)
- содержит хотябы один знак пунктуации:
!"#$%&'()*+,-./:;<=>?@[\]^_``{|}~ - не имеют 6 и более подряд совпадающих символов типа "zzzzzz", "000000"
- не имеет "плохих" последовательностей типа "123456", "abcdef", "qwerty"
- Захват только непустых значений колонок: PCRE
- Как распарсить CSV строку в таблицу? PCRE, PostgreSQL
Ищем до первого найденного управляющего символа по регулярному выражению /[\x00-\x1f](?<![\x08\x09\x0c\x0a\x0d])/ (одинаково в диалектах PCRE и JS)
JSON не должен определяться как бинарный, поэтому исключаем все специальные символы по спецификации:
\brepresents the backspace characterU+0008\trepresents the character tabulation characterU+0009\frepresents the form feed characterU+000C\nrepresents the line feed characterU+000A\rrepresents the carriage return characterU+000D