Подтвердить что ты не робот

Регулярное выражение для операции "И НЕ"

Я ищу общую конструкцию регулярных выражений, соответствующую всем параметрам 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();
}

Я ВСЕГДА просто задаюсь вопросом, существует ли встроенная конструкция регулярного выражения, которая может это сделать.

4b9b3361

Ответ 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 в негативный просмотр, чтобы вручную создать якорь, который вы после.

Это разочарование и боль. "Решение", похоже, использует язык сценариев для выполнения двух регулярных выражений. Один поверх другого. Я удивлен, что такая функциональность не лучше встроена в двигатели регулярных выражений.