Перегляд уперед і назад
Конструкція негативної випереджувальної перевірки [ (?! подвыражение ) ] істинна у разі, якщо збіг для подвыражения у рядку немає. На погляд негативне випередження видається логічним аналогом інвертованого символьного класу, проте з-поміж них є дві принципові відмінності:
l Для успішного збігу інвертований символьний клас повинен з чимось збігатися, що призводить до поглинання тексту. Негативна випереджальна перевірка успішна в тому випадку, якщо вираз не співпадає ні з чим. Ця обставина продемонстрована у другому та третьому прикладах, наведених нижче.
l Символьний клас (інвертований чи ні) збігається з одним символом цільового тексту. Випереджальна перевірка (позитивна або негативна) може застосовуватися до як завгодно складного регулярного виразу.
Розглянемо кілька прикладів випереджальної перевірки:
[Bill (? = spc The Cat spc Clinton)]
Збігається з Bill, але лише в тому випадку, якщо далі слідує spc The spc Cat або spc Clinton.
Збігається з числом, якщо за ним не йде крапка.
Збігається, якщо об'єкт складається лише з одних літер, але у верхньому регістрі.
Дуже винахідливий (хоч і не найрозумніший) спосіб перевірки того, чи існують у цільовому тексті збіги для [this] і для [that]. Більш логічне і загалом сумісне рішення - подвійне регулярне вираження /this/&& /that/
Інші характерні приклади наведено у розділі «Синхронізація збігів» . Для вашої розваги наведу особливо хитрий приклад, взятий з розділу «Поділ груп розрядів комами»:
s d # Від однієї до трьох цифр перед комою
(?= # Після чого слідують, але не включаються до збігу.
(?: \ d \ d \ d) + #Декілька кількість триплетів.
(?! \ d) #. за якими не слідує чергова цифра
) # (інакше кажучи, число завершується)
Круглі дужки випереджальної перевірки не зберігають тексту і вважаються парами круглих дужок при нумерації змінних. Тим не менш, вони можуть містити круглі дужки для збереження «імовірно збігається» тексту. Хоча я не рекомендую зловживати цією можливістю, у деяких ситуаціях вона корисна. Наприклад, [ (.*?)(?= ( strong em ) \s *>) ] збігається з усіма символами до тегів HTML strong > або em > , але не включаючи їх. Поглинений текст надається змінною $1 (і, звичайно, змінною $& ), а сам тег strong > або em > , завдяки якому став можливим збіг, присвоюється змінною $2. Якщо вас не цікавить, який саме тег призвів до успішного припинення пошуку, конструкцію […(strong em)…] краще записати у вигляді […(?: strong em)…]], щоб уникнути зайвого збереження тексту. У прикладі с. подвиражение [ (?=(.*)) ] застосовується для імітації $& .
Зберігають круглі дужки в конструкції з негативним випередженням абсолютно безглузді, оскільки ця конструкція збігається лише за відсутності збігу на її подвыражения.
Як справедливо попереджає сторінка керівництва perlre, випереджальна перевірка принципово відрізняється від ретроспективної. Випереджальна перевірка забезпечує істинність умови (наявність чи відсутність збігу для заданого подвыражения) для конкретної початкової позиції та з напрямом пошуку зліва направо. Ретроспективна перевірка, якби вона якимось чином підтримувалася, шукало б збіг справа наліво.
\d+(?!\.)] і [\d+(?=[^.])], збігаються в рядку OH spc 44272. Перше збігається з OH spc 44272, адруге - з OH spc 44272.
Пам'ятайте: максимальний квантифікатор завжди відступає, якщо це необхідно для загального збігу. Оскільки [ \ d +(?=[^.]) ] вимагає, щоб після числа, що збіглося, слідував символ, відмінний від точки, квантифікатор поступається частиною числа, щоб при необхідності вона могла інтерпретуватися як «не-точка».
Важко сказати, навіщо могли б знадобитися такі висловлювання, та їх, мабуть, слід було записати як [ \ d +(?![\ d .]) ] і [ \ d +(?=[^.\ d ]) ].
Наприклад, вираз [(?!000)\d\d\d] означає «збіг з трьома цифрами, якщо це не 000». Тим не менш, ви повинні добре розуміти, що воно не означає "збіг з трьома цифрами, якщо їм не передує 000". Це вже було б ретроспективною перевіркою, яка не підтримується в Perl і взагалі в жодному з відомих мені діалектів регулярних виразів. Втім, будь-який початковий якір (тип, рядок чи слово) можна як обмежений різновид ретроспективної перевірки.
Будьте уважні з негативною випереджальною перевіркою на початку виразу. Вираз [\w+] збігається з першим словом у рядку, проте поставити на початок [(?! cat)] недостатньо для того, щоб вираз означав «перше слово, що не починається з cat». Вираз [(?! cat) \ w +] не може збігтися на початку cattle, але ніщо не завадить йому збігтися з cattle. Для отримання бажаного ефекту необхідно вжити додаткових заходів - наприклад, [\b(?!cat)\w+].