- PVSM.RU - https://www.pvsm.ru -
Это перевод небольшой заметки, написанной вчера Lea Verou [1]
В ней предлагается интересная техника для решения повседневных задач. В самой статье нету ничего нового, но это хорошее обобщение полезной информации.
Информация в статье касается ECMAScript, но может использоваться и в других RegExp Движках (хотя и есть вероятность, что там есть более подходящее решение).
Если примеры кажутся вам сложными, рекомендую играть с ними в консоли, по мере прочтения. И Заранее прощу прочтение за пугающее название.
Если вы какое-то время используете регулярные выражения, то наверняка вы сталкивались с разными вариантами следующих задач:
Несмотря на то, что в ECMAScript есть циркумфлекс (^), для исключения набора символов, у нас нету возможности, исключить что-то более сложное.
Кроме того, у нас и есть вертикальная черта (|) обозначающая «ИЛИ», но нас нету ничего, что обозначало бы «И», и ничего что обозначало бы «КРОМЕ» (Исключение). Можно проделать все эти действия с несложным набором символов, с помощью символьных классов, но с со сложными последовательностями такое не получится.
Тем не менее, мы можем имитировать все три операции, воспользовавшись тем, что Lookahead условия не захватывают символы и не сдвигают позицию поиска. Мы можем просто продолжить искать соответствие дальше, и они будут совпадать с нужной нам подстрокой, поскольку Lookahead не захватывает ничего…
В качестве простого примера: выражение /^(?! мяу)w{3}$/ захватит любое слово из трех символов, не содержащее слово «мяу». Это очеть простоый вариант исключения.
Вот решение для задачи, предложенной выше: /^(?!d+[50]0)d{3}$/.
Для пересечения (И), мы просто можем выстроить в цепочку несколько позитивных lookahead-условий, а последним шаблоном захватить нужную нам строку (Если оставить только Lookahead условия, то мы все равно получим верный ответ, но можем получить неверные соответствия). Например, решение для задачи с паролем, приведенной выше, будет таким: /^(?=.*d)(?=.*[a-z])(?=.*[W_]).{6,}$/i.
Если вы хотите, чтобы ваши регулярные выражения работали в Internet Explorer 8 версии и ниже, важно знать об этой ошибке [2] и изменить ваши регулярные выражения соответствнно
Отрицание — проше всего. Нам всего лишь нужно негативное lookahead-условие и .+, чтобы захватить подстроку, прошедшую проверку. Например, решение для предложенной выше задачи, будет выглядеть так: /^(?!.*foo).+$/. Стоит, правда, признать, что из всего списка, отрицание неименее полезно
В этой технике присутствуют некоторые сложности. В основном это связано с тем, что захватывается в результате. (Убедитесь, что захватывающий шаблон вне lookahead-условий захватывают всю строку, которая вам нужна)
Steven Levithan копает еще глубже, и пытается имитировать операторы условия [3] и атомарные группы [4]. Прощай
Утилита [6], разбирающая регулярные выражения по частям и объясняющая их
JS библиотека [7], значительно облегчающая работу с регулярными выражениями и добавляющая им функционал.
Автор: z6Dabrata
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/7548
Ссылки в тексте:
[1] Lea Verou: http://lea.verou.me/
[2] этой ошибке: http://blog.stevenlevithan.com/archives/regex-lookahead-bug
[3] операторы условия : http://blog.stevenlevithan.com/archives/mimic-conditionals
[4] атомарные группы: http://blog.stevenlevithan.com/archives/mimic-atomic-groups
[5] мозг: http://www.braintools.ru
[6] Утилита : http://www.myezapp.com/apps/dev/regexp/show.ws
[7] JS библиотека: http://xregexp.com/
Нажмите здесь для печати.