Регулярное выражение напротив - PullRequest
23 голосов
/ 12 мая 2009

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

http://zijab.blogspot.com/2008/09/finding-opposite-of-regular-expression.html утверждает, что вы должны заключить в регулярное выражение

/^((?!^ MYREGEX ).)*$/

, но это не похоже на работу. Если у меня есть регулярное выражение

/[a|b]./

, строка "abc" возвращает false как с моим регулярным выражением, так и с обратным предложением, предложенным zijab,

/^((?!^[a|b].).)*$/

. Можно ли написать обратное выражение регулярного выражения, или я неправильно думаю?

Ответы [ 7 ]

12 голосов
/ 12 мая 2009

Не могли бы вы просто проверить, нет ли совпадений? Я не знаю, какой язык вы используете, но как насчет этого псевдокода?

if (!'Some String'.match(someRegularExpression))
    // do something...

Если вы можете изменить только регулярное выражение, то тот, который вы получили по вашей ссылке, должен работать:

/^((?!REGULAR_EXPRESSION_HERE).)*$/
9 голосов
/ 13 мая 2009

Причина, по которой ваше перевернутое регулярное выражение не работает, заключается в том, что '^' внутри отрицательного взгляда:

/^((?!^[ab].).)*$/
      ^            # WRONG

Возможно, в vim все по-другому, но в каждом варианте регулярного выражения, с которым я знаком, каретка соответствует началу строки (или началу строки в многострочном режиме). Но я думаю, что это была просто опечатка в записи блога.

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

"abc" =~ /[ab]./

Но в Java это не так:

"abc".matches("[ab].")

Это потому, что регулярное выражение, переданное методу matches(), неявно закреплено на обоих концах (то есть /^[ab].$/).

Принимая более распространенную семантику Perl, /[ab]./ означает, что целевая строка содержит последовательность, состоящую из 'a' или 'b', за которой следует хотя бы один символ (разделитель строк). Другими словами, в ЛЮБОЙ точке условие ИСТИНА. Обратный результат этого утверждения в КАЖДОМ пункте - условие ЛОЖЬ. Это означает, что перед тем, как использовать каждый символ, вы выполняете отрицательный просмотр, чтобы подтвердить, что этот символ не является началом соответствующей последовательности:

(?![ab].).

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

/^(?:(?![ab].).)*$/

Это общая идея, но я не думаю, что можно инвертировать каждый регулярное выражение - не тогда, когда исходные регулярные выражения могут включать в себя положительные и отрицательные обходные пути, неохотные и притяжательные квантификаторы, а кто-знает- что.

6 голосов
/ 12 мая 2009

Вы можете инвертировать набор символов, написав ^ в начале ([^…]). Таким образом, противоположное выражение [ab] (соответствует a или b) равно [^ab] (не соответствует ни a, ни b).

Но чем сложнее становится ваше выражение, тем сложнее и дополнительное выражение. Пример:

Вы хотите соответствовать буквальному foo. Выражение, которое соответствует чему-либо еще, кроме строки, содержащей foo, должно соответствовать либо

  1. любая строка, которая короче foo (^.{0,2}$) или
  2. любая строка длиной три символа, которая не foo (^([^f]..|f[^o].|fo[^o])$) или
  3. любая более длинная строка, которая не содержит foo.

Все вместе это может работать:

^[^fo]*(f+($|[^o]|o($|[^fo]*)))*$

Но обратите внимание: это относится только к foo.

2 голосов
/ 03 марта 2011

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

1 голос
/ 10 июня 2011

В perl вы можете противодействовать с $string !~ /regex/;.

0 голосов
/ 14 декабря 2017

Java Regexps имеет интересный способ сделать это (можете протестировать здесь ), где вы можете создать жадное необязательное совпадение для желаемой строки, а затем сопоставить данные после нее. Если жадное совпадение не удается, оно необязательно, поэтому не имеет значения, если оно выполнено успешно, ему нужны дополнительные данные для сопоставления со вторым выражением, и поэтому происходит сбой.

Это выглядит нелогично, но работает.

Например, (foo)?+.+ соответствует bar, foox и xfoo, но не соответствует foo (или пустой строке).

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

0 голосов
/ 09 сентября 2014

С помощью grep вы можете использовать --invert-match или -v.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...