Regex lookahead, lookbehind и атомные группы

330

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

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group
  • 18
    Почему на сайте regex нет такой простой таблицы? Вместо этого у них есть блоки текста, объясняющие только. regular-expressions.info/lookaround.html
  • 3
    @Whitecat Попробуйте: regex101.com regexr.com
Теги:
lookaround

3 ответа

633
Лучший ответ

Примеры

Учитывая строку foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

Вы также можете объединить их:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

Определения

Смотри вперед позитивно (?=)

Найдите выражение A, за которым следует выражение B:

A(?=B)

Смотри вперед негатив (?!)

Найдите выражение A, где выражение B не следует:

A(?!B)

Смотри за позитивом (?<=)

Найдите выражение A, где предшествует выражение B:

(?<=B)A

Смотреть за минусом (?<!)

Найдите выражение A, где выражение B не предшествует:

(?<!B)A

Атомные группы (?>)

Атомная группа выходит из группы и выбрасывает альтернативные шаблоны после первого сопоставленного шаблона внутри группы (обратное отслеживание отключено).

  • (?>foo|foot)s примененные к foots будут соответствовать его 1-му альтернативному foo, затем потерпят неудачу, поскольку s не сразу следует, и остановится, поскольку обратный трекинг отключен

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

  • (foo|foot)s применяется к foots:

    1. сопоставьте его 1-й альтернативе foo, затем потерпите неудачу, так как s не сразу следует в foots, и вернитесь к его 2-й альтернативе;
    2. сопоставьте его 2-ю альтернативную foot, затем добейтесь успеха, поскольку s немедленно следует в foots, и остановитесь

Некоторые ресурсы

  • 1
    Что вы подразумеваете под "находит второй бар" часть? В выражении / строке есть только одна строка. Спасибо
  • 1
    @ziggy проверяемая строка - "foobarbarfoo". Как вы можете видеть, в строке есть два foo и два бара.
Показать ещё 5 комментариев
190

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

Подробнее читайте regular-expression.info.

  • Положительный взгляд:

Синтаксис:

(?=REGEX_1)REGEX_2

Соответствует только если соответствует REGEX_1; после сопоставления REGEX_1 совпадение отбрасывается и поиск REGEX_2 начинается с той же позиции.

Пример:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 - это [a-z0-9]{4}$, который соответствует четырем буквенно-цифровым символам, за которыми следует конец строки.
REGEX_2 - это [a-z]{1,2}[0-9]{2,3}, который соответствует одной или двум буквам, за которыми следуют две или три цифры.

REGEX_1 гарантирует, что длина строки действительно равна 4, но не использует никаких символов, поэтому поиск REGEX_2 начинается с того же места. Теперь REGEX_2 гарантирует соответствие строки другим правилам. Без надежного поиска он будет соответствовать строкам длиной три или пять.

  • Отрицательный взгляд

Синтаксис:

(?!REGEX_1)REGEX_2

Соответствует только если REGEX_1 не соответствует; после проверки REGEX_1 поиск REGEX_2 начинается с той же позиции.

Пример:

(?!.*\bFWORD\b)\w{10,30}$

Просматриваемая часть проверяет FWORD в строке и терпит неудачу, если она ее обнаружит. Если он не находит FWORD, поиск вперед преуспевает, и следующая часть проверяет, что длина строки составляет от 10 до 30 и что она содержит только символы слов a-zA-Z0-9_

Look-behind похож на look-ahead: он просто смотрит за текущую позицию курсора. Некоторые ароматы регулярных выражений, такие как javascript, не поддерживают утверждения look-behind. И большинство ароматов, которые его поддерживают (PHP, Python и т.д.), Требуют, чтобы часть обратного следа имела фиксированную длину.

  • Атомные группы в основном отбрасывают/забывают последующие токены в группе после совпадения токенов. Просмотрите эту страницу для примеров атомных групп
  • 0
    Следуя вашему объяснению, похоже, не работает в javascript, /(?=source)hello/.exec("source...hummhellosource ") = null. Ваше объяснение правильно?
  • 0
    @HelinWang Это объяснение правильно. Ваше регулярное выражение ожидает строку, которая является одновременно источником и привет!
Показать ещё 3 комментария
0

Грохоты быстро исчезают.
Как отличить lookahead и lookbehind? Пройдите 2 минуты тура со мной:

(?=) - positive lookahead
(?<=) - positive lookbehind

предполагать

    A  B  C #in a line

Теперь, мы спрашиваем B, где вы?
B имеет два решения, объявляющих его местоположение:

Один, B имеет A вперед и имеет C bebind
Два, B впереди (lookahead) C и сзади (lookhehind) A.

Как мы видим, в обоих решениях противоположные и дальнейшие противоположны.
Regex - это решение Two.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню