Регулярное выражение для операции "И НЕ"
Я ищу общую конструкцию регулярных выражений, соответствующую всем параметрам x EXCEPT, соответствует шаблону y. Это трудно объяснить как полностью, так и кратко... см. Материал Nonimplication для формального определения.
Например, сопоставьте любой символ слова (\w
) EXCEPT 'p'. Примечание. Я вычитаю небольшой набор (буква "p" ) из большего набора (все словальные символы). Я не могу просто сказать [^p]
, потому что это не учитывает больший ограничивающий набор только словных символов. Для этого небольшого примера, конечно, я мог бы вручную восстановить что-то вроде [a-oq-zA-OQ-Z0-9_]
, что больно, но выполнимо. Но я ищу более общую конструкцию, так что по крайней мере большой положительный набор может быть более сложным выражением. Как и матч ((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)
, за исключением случаев, когда он начинается с "My".
Изменить. Я понимаю, что это был плохой пример, так как исключение материала в начале или конце - это ситуация, в которой работают негативные взгляды и взгляды. (Богемианский я все еще дал вам преимущество для иллюстрации этого). Итак... как насчет исключения совпадений, содержащих "Мой" где-то посередине?... Я все еще действительно ищу общую конструкцию, такую как эквивалент регулярного выражения следующего псевдо-sql
select [captures] from [input]
where (
input MATCHES [pattern1]
AND NOT capture MATCHES [pattern2]
)
Если ответ "это не существует, и вот почему...", я тоже хотел бы это знать.
Изменить 2. Если бы я хотел определить свою собственную функцию для этого, это будет что-то вроде (здесь версия С# LINQ):
public static Match[] RegexMNI(string input,
string positivePattern,
string negativePattern) {
return (from Match m in Regex.Matches(input, positivePattern)
where !Regex.IsMatch(m.Value, negativePattern)
select m).ToArray();
}
Я ВСЕГДА просто задаюсь вопросом, существует ли встроенная конструкция регулярного выражения, которая может это сделать.
Ответы
Ответ 1
Это будет соответствовать любому символу, который является словом, и не является p
:
((?=[^p])\w)
Чтобы решить ваш пример, используйте отрицательный внешний вид для "My" в любом месте ввода, то есть (?!.*My)
:
^(?!.*My)((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)
Обратите внимание на якорь для начала ввода ^
, который требуется для его работы.
Ответ 2
Интересно, почему люди пытаются делать сложные вещи в больших монолитных регулярных выражениях?
Почему вы не можете просто разбить проблему на части, а затем сделать очень легкие регулярные выражения, чтобы они соответствовали друг другу? В этом случае сначала сопоставьте \w
, затем сопоставьте [^p]
, если это первое совпадение выполнено успешно. Perl (и другие языки) позволяет создавать действительно сложные выглядящие регулярные выражения, которые позволяют вам делать именно то, что вам нужно делать в одном большом blobby-regex (или, как это может быть, с коротким и быстрым крипторежимом), но ради того, кому это нужно, чтобы прочитать (и поддерживать!) код, как только вы ушли, вам нужно полностью документировать его. Лучше тогда упростить понимание с самого начала.
Извините, rant.
Ответ 3
После ваших изменений его все еще отрицательный взгляд, но с дополнительным квантором.
Если вы хотите, чтобы вся строка не содержала "Мой", вы можете сделать это
(?!.*My)^.*$
Смотрите здесь в Regexr
Это будет соответствовать любой последовательности символов (с .*
в конце), а (?!.*My).*
в начале будет терпеть неудачу, если в строке есть "Мой".
Если вы хотите сопоставить что-либо, что не соответствует "My", тогда используйте anchors
(?!^My$).*
Ответ 4
Итак, просмотрев эти темы в RegEx: lookahead, lookbehind, nesting, AND, recursion, подпрограммы, условные выражения, привязки и группы, я пришел к выводу, что существует no solution, который удовлетворяет тому, что вы просите.
Причина, по которой lookahead не работает, заключается в том, что она не выполняется в этом относительно простом случае:
Три слова без Моих включены как один.
Regex:
^ (?!. * My. *) (\ b\w +\b\s\b\w +\b\s\b\w +\b)
Матчи:
включен как один
Первые три слова не совпадают, потому что после них происходит. Если "My" находится в конце всей строки, вы никогда не будете соответствовать чему-либо, потому что каждый lookahead потерпит неудачу, потому что они все это заметят.
Проблема заключается в том, что в то время как lookahead имеет неявный якорь относительно того, где он начинает свое соответствие, нет способа прекратить, когда lookahead завершает поиск с помощью привязки, основанной на результате другой части RegEx. Это означает, что вам действительно нужно дублировать весь RegEx в негативный просмотр, чтобы вручную создать якорь, который вы после.
Это разочарование и боль. "Решение", похоже, использует язык сценариев для выполнения двух регулярных выражений. Один поверх другого. Я удивлен, что такая функциональность не лучше встроена в двигатели регулярных выражений.