CodingRegExp

Lookaround и валидация пароля

RegExp: lookaround

Lookahead и lookbehind, в совокупности называемые «lookaround», являются утверждениями нулевой длины, которые проверяют совпадение с указанными символами, но возвращают только наличие или отсутствие совпадения.

lookaround Пример Примечание
positive lookahead (?=…) ~[\d]{1,6}(?= руб\.)~
поиск и захват сумм, выраженных в рублях
используется при необходимости получить все совпадения с выражением, за которым следует определенный шаблон
negative lookahead (?!…) ~а(?!ла)~
поиск и захват подстроки ‘а’, непосредственно за которой не следует подстрока ‘ла’
используется, при необходимости получить все совпадения с выражением, за которым не следует определенный шаблон
positive lookbehind (?<=…) ~(?<=\$)[\d]{1,6}~
поиск и захват сумм, выраженных в долларах
используется для получения всех совпадений, которым предшествует определенный шаблон
negative lookbehind (?<!…) ~(?<!упа)ла~
поиск и захват подстроки ‘ла’, не предворенной подстрокой ‘упа’
используется для получения всех совпадений, которым не предшествует определенный шаблон

Внутри lockahead можно использовать любое регулярное выражение, в отличии от lookbehind здесь не будут работать группы захвата.

Очевидно, что позитивные взгляды возвращают true при наличии совпадения, отрицательные - при отсутствии такового.

И lookbehind смотрят совпадение перед захватываемым выражением, а lookahead - после. Пока все просто.

Сравнение: со Смотрителями или без них?

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

Например, для поиска слова из 4 символов, содержащего подстроку ‘con’. Без использования Смотрителей у меня получилось ‘~(^|\s)\wcat(\s|$)|(^|\s)cat\w(\s|$)~g‘.

И это для латиницы (используется \w) и всего для двух вариантов. При добавлении или усложнении условий выражение становится нечитабельным из-за своих размеров. Кроме того, полученные совпадения необходимо тримить от захваченных пробельных символов.

С использованием Смотрителей: ‘~(?=(^|\s))(?=.*cat)\w{4}(?=(\s|$))~gm‘.

Попытаюсь расписать полученное выражение:

  1. (?=(^|\s))‘ - Позитивный Смотритель Вперёд проверяет наличие перед искомым выражением пробельного символа либо начала строки;
  2. (?=.*cat)‘ - Второй Позитивный Смотритель Вперёд проверяет наличие в искомой строке подстроки ‘cat’, без указания позиции;
  3. \w{4}‘ - непосредственно поиск подстроки, содержащей 4 символа \w;
  4. (?=(\s|$))‘ - Третий Позитивный Смотритель Вперёд производит поиск пробельного символа либо конца строки за искомой строкой.

Пример: валидация пароля

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

В данном регулярном выражении используется positive lookahead - Позитивный Смотритель Вперёд, ищущий наличие в строке трех выражений, причем каждое выражение начинается с необязательных символов - будет найдено в любой позиции строки. В последней части проверяется количество символов и отсеиваются строки с запрещенными символами:

// UsersController.php or UserRequest
...
request()->validate([
            'new_password' => [
                'string',
                'min:8',
                'max:255',
                'regex:~(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[\da-zA-Z]{8,}~',
                'confirmed'
            ],
            'password' => 'string',
        ]);

2
Оставить комментарий

avatar
1 Цепочка комментария
1 Ответы по цепочке
0 Последователи
 
Популярнейший комментарий
Цепочка актуального комментария
  Подписаться  
новее старее большинство голосов
Уведомление о