Синтаксис регулярного виразу для “нічого не збігається”?


83

У мене є механізм шаблонів python, який активно використовує регулярний вираз. Він використовує конкатенацію, як:

re.compile( regexp1 + "|" + regexp2 + "*|" + regexp3 + "+" )

Я можу змінити окремі підрядки (регулярний вираз1, регулярний вираз2 та ін.).

Чи є якийсь невеликий та легкий вираз, який нічого не збігається, який я можу використовувати всередині шаблону, де я не хочу ніяких збігів? На жаль, іноді '+' або '*' додається до атома регулярного виразу, тому я не можу використовувати порожній рядок - це призведе до помилки "нічого повторювати".



3
Чи можна заголовок сформулювати так: "Регулярний вираз не відповідає нічому"? Збіг нічого не означає успішне збіг порожнього рядка.
BamaPookie

Відповіді:


126

Це не повинно збігатися ні з чим:

re.compile('$^')

Отже, якщо ви заміните регулярні вирази1, регулярні вирази2 та регулярні терміни3 на '$ ^', буде неможливо знайти відповідність. Якщо ви не використовуєте багаторядковий режим.


Після деяких тестів я знайшов краще рішення

re.compile('a^')

Неможливо зіставити і не вдасться раніше попереднього рішення. Ви можете замінити будь-яким іншим символом, і це завжди буде неможливо зіставити


Що точно не відповідатиме нічому, і чи легкий для обробки двигуном регулярних виразів? (не хочу, щоб мої туписті регулярні вирази їли багато процесора)
grigoryvp

@ Око пекла. Він повинен бути легким. Це спробує узгодити кінець рядка з наступним початком рядка. Що неможливо одним рядком.
Надя Алрамлі 02

1
Але це можливо з декількома рядками, звичайно (залежно від того, чи увімкнено прапор) - для рішення, яке працює, увімкнено чи ні, див. Мою відповідь.
Пітер Боутон

16
Звичайний вираз "$ ^" відповідає порожньому рядку, принаймні в деяких реалізаціях. Другий - краще.
Роман Старков

@romkyns Другий не відповідає порожньому рядку в моєму дзвінку до PyQt4 QtCore.QRegExp. Настільки погано, що напевно було б легше виконати.
Joël

44

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


4
Правильно, я теж збирався опублікувати це теж. Це найкращий спосіб, якщо ваша мова підтримує пошукові голови. Так само (? =) Відповідає кожному рядку.
Брайан Карпер 02

16

Щоб зіставити порожній рядок - навіть у багаторядковому режимі - ви можете використовувати \A\Z, тому:

re.compile('\A\Z|\A\Z*|\A\Z+')

Різниця полягає в тому, що \Aі \Zє початок і кінець рядка , в той час , ^і $вони можуть відповідати початок / кінець рядка , так що $^|$^*|$^+потенційно може відповідати рядку , що містить символ нового рядка (якщо прапор включений).

А щоб не зіставити нічого (навіть порожній рядок), просто спробуйте знайти вміст перед початком рядка, наприклад:

re.compile('.\A|.\A*|.\A+')

Оскільки до \ A (за визначенням) не може бути жодного символу, це завжди не буде збігатися.


Ваш виглядає приємніше мого, оскільки я припускаю, що він вийшов би швидше, ніж використання кінця рядка.
ShuggyCoUk, 02

Пітере, ти використовуєш \ z (нижній регістр), тоді як мій кишеньковий посібник Python каже мені, що твердження про кінець рядка - \ Z (верхній регістр) ?!
ThomasH

ThomasH, вони обидва є кінцем рядка, але версія верхнього регістру дозволяє завершувати новий рядок, тоді як нижня - ні.
Пітер Боутон

Mh, цікаво, я ніде не знаходжу це документовано. Крім того, re.search ("boo \ z", "fooboo") не повертає об'єкт збігу, тоді як re.search ("boo \ Z", "fooboo) робить. Навпаки, re.search (" boo \ z "," foobooz ") збігається, що говорить про те, що '\ z' просто інтерпретується як 'z', так ?! (Це в Python 2.6).
ThomasH

Ах, вибачте, я думав, що Python є PCRE, але виявляється, є кілька відмінностей, і це одна з них. (Див. "Якіри" на регулярних виданнях.info/refflavors.html )
Пітер Боутон


1

Ви можете використовувати
\z..
Це абсолютний кінець рядка, за яким слідують два слова

Якщо +або *призначається в кінці, це все одно працює, відмовляючи відповідати нічому


Чому два чого завгодно? IIRC \zне дозволяє відстежувати нові рядки, на відміну \Z, так, чи не достатньо одного? Або це дивний захист проти *(чому ви
захищаєтесь

0

Або скористайтеся розумінням списку, щоб видалити непотрібні записи регулярних виразів та об’єднатись, щоб об’єднати їх усі. Щось на зразок:

re.compile('|'.join([x for x in [regexp1, regexp2, ...] if x != None]))

Не забудьте додати кілька коментарів поруч із цим рядком коду :-)

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