Регулярное выражение противоположно
Можно ли написать регулярное выражение, которое возвращает обратное значение желаемого результата? Регулярные выражения обычно include в себя – поиск матчей. Я хочу иметь возможность преобразовать регулярное выражение в его противоположность – утверждая, что совпадений нет. Это возможно? Если да, то как?
http://zijab.blogspot.com/2008/09/finding-opposite-of-regular-expression.html заявляет, что вы должны скопировать ваше регулярное выражение с помощью
/^((?!^ MYREGEX ).)*$/
, но это, похоже, не работает. Если у меня есть регулярное выражение
- Матч при каждом втором появлении
- Объединить Regexp?
- Разница между \ b и \ B в регулярном выражении
- Регулярное выражение для соответствия внешним скобкам
- Regex: игнорировать чувствительность к регистру
/[a|b]./
, строка «abc» возвращает false как с моим регулярным выражением, так и с обратным предложением, предложенным zijab,
/^((?!^[a|b].).)*$/
, Можно ли написать обратное выражение регулярного выражения, или я неправильно думаю?
- Регулярное выражение для исключения слова / строки
- Преобразование символа в верхний регистр с использованием регулярных выражений (EditPad Pro)
- Python Regex - Как получить позиции и значения совпадений
- Почему регулярные выражения имеют экспоненциальное время работы?
- regex, чтобы совместить слово с уникальными (не повторяющимися) символами
- Регулярное выражение для принудительного применения сложных паролей, соответствующих 3 из 4 правил
- Regex: Согласование путем исключения, без надежды - возможно ли это?
- Как проверить имя пользователя с регулярным выражением?
Причина, по которой ваше инвертированное регулярное выражение не работает, происходит из-за « ^
» внутри негативного outlookа:
/^((?!^[ab].).)*$/ ^ # WRONG
Возможно, это отличается от vim, но в любом регулярном выражении, с которым я знаком, карет соответствует началу строки (или началу строки в многострочном режиме). Но я думаю, что это была опечатка в блоге.
Вам также необходимо принять во внимание семантику используемого инструмента регулярного выражения. Например, в Perl это верно:
"abc" =~ /[ab]./
Но в Java это не так:
"abc".matches("[ab].")
Это связано с тем, что регулярное выражение, переданное методу /^[ab].$/
matches()
неявно закреплено на обоих концах (например, /^[ab].$/
).
Принимая более распространенную семантику Perl, /[ab]./
означает, что целевая строка содержит последовательность, состоящую из «a» или «b», за которой следует по крайней мере один символ (нестрочный разделитель). Другими словами, в ЛЮБОЙ точке условие TRUE. Обратное к этому утверждению: в КАЖДОЙ точке условие FALSE. Это означает, что перед тем, как вы будете потреблять каждый символ, вы выполняете отрицательный просмотр, чтобы подтвердить, что символ не является началом соответствующей последовательности:
(?![ab].).
И вы должны изучить каждого персонажа, поэтому регулярное выражение должно быть привязано с обоих концов:
/^(?:(?![ab].).)*$/
Это общая идея, но я не думаю, что можно инвертировать каждое регулярное выражение, а не когда исходные регулярные выражения могут включать в себя положительные и отрицательные образы, неохотные и притяжательные кванторы, а кто-что знает.
Не могли бы вы просто проверить, нет ли совпадений? Я не знаю, какой язык вы используете, но как насчет этого псевдокода?
if (!'Some String'.match(someRegularExpression)) // do something...
Если вы можете изменить только регулярное выражение, то тот, который вы получили из вашей ссылки, должен работать:
/^((?!REGULAR_EXPRESSION_HERE).)*$/
Вы можете инвертировать набор символов, записав a ^
в начале ( [^…]
). Таким образом, противоположное выражение [ab]
(совпадающее с a
или b
) равно [^ab]
(не соответствует ни a
ни b
).
Но чем сложнее ваше выражение, тем сложнее дополнительное дополнение. Пример:
Вы хотите соответствовать буквальному foo
. Выражение, которое соответствует любому другому, кроме строки, содержащей foo
должно соответствовать либо
- любая строка, длина которой меньше
foo
(^.{0,2}$
), или - любые три строки длинной строки, которые не являются
foo
(^([^f]..|f[^o].|fo[^o])$
), или - любая более длинная строка, которая не содержит
foo
.
Все это может сработать:
^[^fo]*(f+($|[^o]|o($|[^fo]*)))*$
Но обратите внимание: это относится только к foo
.
Вы также можете сделать это (в python) с помощью re.split
и расщепления на основе вашего регулярного выражения, возвращая тем самым все части, которые не соответствуют регулярному выражению, как найти обратное выражение регулярного выражения
В perl вы можете противостоять $string !~ /regex/;
,
С помощью grep вы можете использовать --invert-match
или -v
.
Java Regexps имеют интересный способ сделать это (можно проверить здесь ), где вы можете создать жадное необязательное соответствие для нужной строки, а затем сопоставить данные после нее. Если жадное совпадение терпит неудачу, оно необязательно, так что это не имеет значения, если он преуспевает, ему нужны дополнительные данные для соответствия второму выражению, и это терпит неудачу.
Он выглядит контр-интуитивным, но работает.
Например, (foo)?+.+
foox
bar
, foox
и xfoo
но не будет соответствовать foo
(или пустой строке).
Это возможно в других диалектах, но не может заставить его работать самостоятельно (они кажутся более склонными к отступлению, если второе совпадение не удастся?)