Синтаксис регулярного выражения для «ничего не найдено»?

83

У меня есть шаблонизатор Python, который активно использует регулярное выражение. Он использует конкатенацию, например:

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

Я могу изменить отдельные подстроки (regexp1, regexp2 и т. Д.).

Есть ли какое-нибудь маленькое и легкое выражение, которое ничего не соответствует, которое я могу использовать внутри шаблона, где мне не нужны совпадения? К сожалению, иногда к атому регулярного выражения добавляется «+» или «*», поэтому я не могу использовать пустую строку - это вызовет ошибку «нечего повторять».

Григорьевп
источник
1
stackoverflow.com/questions/1723182/…
Пол Томблин
3
Можно ли лучше сформулировать заголовок как «Регулярное выражение не соответствует чему-либо»? Отсутствие совпадений означает успешное совпадение пустой строки.
BamaPookie

Ответы:

126

Это не должно ничего совпадать:

re.compile('$^')

Поэтому, если вы замените regexp1, regexp2 и regexp3 на '$ ^', будет невозможно найти совпадение. Если вы не используете многострочный режим.


После некоторых тестов я нашел лучшее решение

re.compile('a^')

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

Надя Алрамли
источник
Это не будет точно совпадать и легковесно для обработки движком регулярных выражений? (не хочу, чтобы мои
регулярные выражения-
@ Глаз ада. Он должен быть легким. Это попытается сопоставить конец строки, за которой следует начало строки. Что невозможно в одной строке.
Надя Алрамли 02
1
Но возможно, конечно, с несколькими строками (в зависимости от того, включен ли флаг) - для решения, которое работает независимо от того, включен флаг или нет, см. Мой ответ.
Питер Ботон,
16
Регулярное выражение «$ ^» соответствует пустой строке, по крайней мере, в некоторых реализациях. Второй лучше.
Роман Старков
@romkyns Второй не соответствует пустой строке в моем вызове PyQt4 QtCore.QRegExp. Настолько плохо, что наверняка было бы легче казнить.
Joël
44

(?!)всегда не должно совпадать. Это отрицательный прогноз нулевой ширины. Если то, что указано в скобках, совпадает, то все совпадение не выполняется. Учитывая, что в нем ничего нет, он не сможет найти ничего (включая ничего).

Час. Оуэнс
источник
4
Хорошо, я тоже собирался опубликовать это. Это лучший способ, если ваш язык поддерживает опережающий просмотр. Аналогично (? =) Соответствует каждой строке.
Брайан Карпер,
16

Чтобы сопоставить пустую строку - даже в многострочном режиме - вы можете использовать \A\Z, поэтому:

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

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

И чтобы ничего не найти (даже пустая строка), просто попытайтесь найти содержимое до начала строки, например:

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

Поскольку перед \ A не может быть никаких символов (по определению), это всегда не соответствует.

Питер Ботон
источник
Ваш выглядит лучше, чем мой, поскольку я предполагаю, что он выйдет быстрее, чем при использовании конца строки.
ShuggyCoUk
Питер, вы используете \ z (нижний регистр), в то время как мой карманный справочник Python сообщает мне, что утверждение конца строки - \ Z (верхний регистр) ?!
ThomasH
ThomasH, они оба являются концом строки, но версия в верхнем регистре допускает завершающую новую строку, а нижняя - нет.
Питер Ботон,
М-м, интересно, я нигде не нашел документального подтверждения. Кроме того, re.search ("boo \ z", "fooboo") не возвращает объект соответствия, в то время как re.search ("boo \ Z", "fooboo) возвращает . Скорее, re.search (" boo \ z "," foobooz ") , что говорит о том, что '\ z' просто интерпретируется как 'z', верно ?! (Это в Python 2.6).
ThomasH
Извините, я думал, что Python - это PCRE, но оказалось, что есть несколько отличий, и это одно из них. (См. «Якоря» на regular-expressions.info/refflavors.html )
Питер Боутон
1

Вы можете использовать
\z..
Это абсолютный конец строки, за которым следуют два любых

Если +или *прикреплен к концу, это все еще работает, отказываясь соответствовать чему-либо

ShuggyCoUk
источник
Почему два из чего-нибудь? IIRC \zне позволяет завершать символы новой строки, в отличие от этого \Z, разве не хватит одной? Или это странная защита против *(почему вы остерегаетесь этого?)
mpen
0

Или используйте некоторое понимание списка, чтобы удалить бесполезные записи регулярного выражения, и соедините их, чтобы собрать их все вместе. Что-то вроде:

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

Не забудьте добавить комментарии рядом с этой строкой кода :-)

Майк Миллер
источник