W3docs

Опережающая и ретроспективная проверка

В этой главе мы подробно рассмотрим поиск совпадений в JavaScript. Узнайте, как применять опережающую и ретроспективную проверку на практике.

Понимание продвинутых возможностей регулярных выражений JavaScript полезно любому разработчику, стремящемуся повысить свои навыки программирования. Среди наиболее мощных и функциональных инструментов этой области — утверждения опережающей и ретроспективной проверки. Они позволяют разработчикам искать паттерны в тексте, не включая сами паттерны в результат. Это руководство предлагает детальное изучение утверждений опережающей и ретроспективной проверки в JavaScript с многочисленными практическими примерами.

Внимание

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

Введение в утверждения опережающей и ретроспективной проверки

Утверждения опережающей и ретроспективной проверки — это утверждения нулевой ширины: они совпадают с позицией в строке, а не с реальными символами. Они позволяют проверять, существует или не существует заданный паттерн в определённой точке строки. Примечание: современные движки JavaScript (ES2018+) поддерживают ретроспективные утверждения переменной длины, хотя некоторые более старые среды могут требовать паттернов фиксированной длины.

Существует четыре утверждения, образованных комбинацией направления (вперёд/назад) и полярности (положительная/отрицательная):

УтверждениеСинтаксисЗначение
Положительная опережающая проверка(?=...)Паттерн должен следовать после этой позиции
Отрицательная опережающая проверка(?!...)Паттерн не должен следовать после этой позиции
Положительная ретроспективная проверка(?<=...)Паттерн должен предшествовать этой позиции
Отрицательная ретроспективная проверка(?<!...)Паттерн не должен предшествовать этой позиции

Почему «нулевая ширина» важна

Поскольку утверждения совпадают с позицией, а не с символами, проверяемый ими текст никогда не включается в совпадение, а позиция чтения движка регулярных выражений не смещается за него. Именно это делает их полезными: можно требовать контекст вокруг совпадения, не включая этот контекст в результат. Фрагмент ниже показывает разницу между обычной захватывающей группой и опережающей проверкой — обе убеждаются, что pie следует за apple, но только группа потребляет текст:

javascript— editable

Если вы только знакомитесь с синтаксисом групп (...), см. Захватывающие группы — синтаксис lookaround использует те же скобки, но добавляет ?=, ?!, ?<= или ?<! сразу после открывающей скобки.

Положительная опережающая проверка

Утверждение положительной опережающей проверки проверяет наличие определённого паттерна впереди текущей позиции в строке. Оно обозначается (?=...). Следующий пример использует положительную опережающую проверку для поиска слова "apple", за которым следует слово "pie":

Опережающая проверка в регулярных выражениях JavaScript соответствует символам

javascript— editable

Отрицательная опережающая проверка

Утверждение отрицательной опережающей проверки проверяет отсутствие определённого паттерна впереди текущей позиции. Оно обозначается (?!...). Следующий пример использует отрицательную опережающую проверку для поиска слова "apple", за которым не следует слово "pie":

Отрицательная опережающая проверка в регулярных выражениях JavaScript

javascript— editable

Положительная ретроспективная проверка

Утверждение положительной ретроспективной проверки проверяет наличие определённого паттерна позади текущей позиции в строке. Оно обозначается (?<=...). Ниже приведён пример кода для поиска слова "pie", которому предшествует слово "apple":

Положительная ретроспективная проверка в регулярных выражениях JavaScript

javascript— editable

Отрицательная ретроспективная проверка

Утверждение отрицательной ретроспективной проверки проверяет отсутствие определённого паттерна позади текущей позиции. Оно обозначается (?<!...). Вот пример для поиска слова "pie", которому не предшествует слово "apple":

Опережающая и ретроспективная проверка

javascript— editable

Практическое применение опережающей и ретроспективной проверки

Проверка надёжности пароля

Требование к надёжным паролям является распространённой задачей в веб-приложениях. Утверждения опережающей проверки можно использовать для валидации различных условий к паролю без потребления символов.


javascript— editable

Здесь каждый (?=...) — это отдельное требование, проверяемое с начала строки. Поскольку каждая опережающая проверка имеет нулевую ширину, все четыре независимо сканируют один и тот же текст, не мешая друг другу, а итоговый [A-Za-z\d@$!%*?&]{8,} — это то, что фактически потребляет пароль. Якоря ^ и $ привязывают проверку ко всей строке, а {8,} — это квантификатор, требующий не менее восьми символов.

Форматирование и разбор данных

Утверждения опережающей и ретроспективной проверки могут помочь при форматировании и разборе сложных структур данных. Хороший пример — вставка запятых в строку чисел для удобочитаемости:


javascript— editable

Это работает путём замены каждой пустой позиции (\B, не-граница слова), за которой следует группа из трёх цифр, повторяющаяся до конца числа. Замыкающий (?!\d) гарантирует, что мы совпадаем только с позициями, где оставшиеся цифры делятся поровну на тройки, поэтому запятая не ставится в самом начале.

Извлечение суммы из цены

Ретроспективная проверка идеально подходит для захвата значения, которое стоит после известного маркера, без захвата самого маркера. Здесь мы извлекаем числовую сумму, следующую за знаком $:

javascript— editable

Ретроспективная проверка (?<=\$) требует наличия $ непосредственно перед числом, но не включает его в результат, поэтому каждое совпадение содержит только цифру. Сравните это с использованием захватывающей группы — группа заставила бы вас читать сумму из match[1], тогда как ретроспективная проверка помещает значение прямо в совпадение.

Действие только при отсутствии следующего паттерна

Отрицательная опережающая проверка позволяет действовать в позиции на основе того, что не следует далее. Этот пример заменяет hello на HI только тогда, когда за ним не следует world:

javascript— editable

Связанные темы

Заключение

Освоение утверждений опережающей и ретроспективной проверки в JavaScript может значительно расширить вашу способность манипулировать строками и анализировать их. Эти мощные инструменты обеспечивают гибкость для проверки паттернов без потребления символов, что делает их незаменимыми при решении сложных задач обработки текста. Используя эти утверждения, разработчики могут создавать более эффективные регулярные выражения, что ведёт к более чистому и поддерживаемому коду.

Практика

Практика
Какие из следующих утверждений об опережающей и ретроспективной проверке в JavaScript верны?
Какие из следующих утверждений об опережающей и ретроспективной проверке в JavaScript верны?
Was this page helpful?