Регекс, дивіться позаду та атомні групи


314

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

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

(?>) - atomic group

18
Чому на веб-сайті regex немає такої простої таблиці, як ця? Натомість у них є лише блоки тексту, що пояснюють. regular-expressions.info/lookaround.html
WhiteCat

3
@Whitecat Спробуйте: regex101.com regexr.com
Андрій

Відповіді:


851

Приклади

Враховуючи рядок 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буде відповідати його першої альтернативи foo, тоді не вдасться, як sце не випливає відразу, і зупиниться, оскільки зворотне відстеження вимкнено

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

  • (foo|foot)sзастосовується до footsзаповіту:

    1. співставити свою першу альтернативу foo, потім провалитися, як sце не випливає foots, і повернути її до другої альтернативи;
    2. відповідати його 2-й альтернативи foot, а потім домогтися успіху, як sнегайно випливає foots, і зупинити.

Деякі ресурси

Інтернет-тестери


1
Що ви маєте на увазі під "знаходить другу смужку"? У виразі / рядку є лише одна смужка. Спасибі
ziggy

2
@ziggy тест, який тестується, "foobarbarfoo". Як ви бачите, в рядку є два foo та два смуги.
skyfoot

4
Чи може хтось пояснити, коли може знадобитися атомна група? Якщо мені потрібно співставити лише першу альтернативу, чому я б хотів дати декілька альтернатив?
arviman

2
Краще пояснення щодо атомної групи на цю відповідь . Може хтось тут редагує, щоб завершити цю тематичну відповідь?
Пітер Краус

5
Лише зауважте, що ця відповідь була важливою, коли я опинився в проекті, який потребував серйозних відбитків. Це відмінне, стисле пояснення зовнішнього вигляду.
Том Кафлін

215

Значення округів - це твердження нульової ширини. Вони перевіряють регулярний вираз (вправо або вліво від поточної позиції - на основі вперед або ззаду), досягає успіху або не вдається, коли знайдеться відповідність (виходячи з того, якщо вона є позитивною чи негативною) і відкидає відповідну частину. Вони не споживають жодного символу - відповідність для регулярного вираження, що слідує за ними (якщо є), почнеться з тієї ж позиції курсору.

Прочитайте regular-expression.info для отримання більш детальної інформації.

  • Позитивний lookahead:

Синтаксис:

(?=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_

Вигляд позаду схожий на вигляд вперед: він просто дивиться за поточну позицію курсору. Деякі аромати регулярного вираження, як-от JavaScript, не підтримують твердження, що знаходяться позаду. І більшість ароматів, які його підтримують (PHP, Python тощо), вимагають, щоб частина, яка оглядається, мала фіксовану довжину.

  • Атомні групи в основному відкидає / забуває наступні лексеми в групі, коли маркер збігається. Перевірте на цій сторінці приклади атомних груп

слідуючи вашим поясненням, схоже, не працює в JavaScript, /(?=source)hello/.exec("source...hummhellosource ") = null. Чи правильне ваше пояснення?
Хелін Ван

@HelinWang Це пояснення правильне. Ваш регекс очікує рядок, який є і джерелом, і привіт!
Amarghosh

@jddxf Догляд допрацювати?
Амаргош

@Amarghosh Я погоджуюсь з "Вони перевіряють регулярний вираз (вправо або вліво від поточної позиції - на основі вперед або ззаду), досягає успіху або не вдається, коли знайдеться відповідність (на основі, якщо вона є позитивною чи негативною) і відкидає відповідне порція. " Таким чином, lookahead повинен перевірити наявність регулярного виразу вправо від поточного положення, а синтаксис позитивного lookahead повинен бути x (? = Y)
jddxf

@Amarghosh відповідатиме (?=REGEX_1)REGEX_2лише тоді, коли REGEX_2прийде після REGEX_1 ?
aandis

0

Швидко обертається.
Як відрізнити lookahead та lookbehind? Візьміть зі собою 2-хвилинну екскурсію:

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

Припустимо

    A  B  C #in a line

Тепер ми запитуємо Б, де ти?
B має два рішення для оголошення місця розташування:

Один, B має A попереду, і C пов'язує
два, B попереду (lookahead) від C і ззаду (lookhehind) A.

Як ми бачимо, позаду і попереду в двох рішеннях протилежні.
Регекс - це рішення два.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.