Я пытаюсь что-то, что, по моему мнению, должно быть достаточно очевидным для меня, но это не так. Я пытаюсь сопоставить строку, которая НЕ содержит определенную последовательность символов. Я пробовал использовать [^ab]
, [^(ab)]
и т.д. Для соответствия строкам, не содержащим "a" или "b", или только "a" или "b", но не соответствует "ab". Примеры, которые я дал, не будут соответствовать "ab" it true, но они также не будут соответствовать "a" , и мне они нужны. Есть ли простой способ сделать это?
Регулярные выражения и отрицание целой группы персонажей
Ответ 1
Используйте отрицательный просмотр:
^(?!.*ab).*$
ОБНОВЛЕНИЕ. В комментариях ниже я заявил, что этот подход медленнее, чем тот, который приведен в Питере.. С тех пор я провел несколько тестов и обнаружил, что это действительно немного быстрее. Однако причина предпочитать эту технику над другой - это не скорость, а простота.
Другой метод, описанный здесь как умеренный алчный токен, подходит для более сложных проблем, таких как сопоставление текста с разделителями, в котором разделители состоят из несколько символов (например, HTML, как Luke прокомментировал ниже). Для проблемы, описанной в вопросе, она переполняется.
Для всех, кто интересуется, я тестировал большой фрагмент текста Lorem Ipsum, подсчитывая количество строк, которые не содержат слова "quo". Это регулярные выражения, которые я использовал:
(?m)^(?!.*\bquo\b).+$
(?m)^(?:(?!\bquo\b).)+$
Я ищу поиск совпадений во всем тексте или разбиваю его на строки и сопоставляю их по отдельности, привязанный lookahead последовательно превосходит плавающий.
Ответ 2
Использование класса символов, такого как [^ab]
, будет соответствовать одиночному символу, который не входит в набор символов. (С ^
является отрицательной частью).
Чтобы соответствовать строке, которая не содержит многосимвольной последовательности ab
, вы хотите использовать отрицательный просмотр:
^(?:(?!ab).)+$
И вышеприведенное выражение, которое вызывается в режиме комментариев регулярных выражений:
(?x) # enable regex comment mode
^ # match start of line/string
(?: # begin non-capturing group
(?! # begin negative lookahead
ab # literal text sequence ab
) # end negative lookahead
. # any single character
) # end non-capturing group
+ # repeat previous match one or more times
$ # match end of line/string
Ответ 3
Да его называют негативным взглядом. Это происходит так: (?!regex here)
. Таким образом, abc(?!def)
будет соответствовать abc не, а затем def. Таким образом, он будет соответствовать abce, abc, abck и т.д.
Аналогично, есть положительный результат - (?=regex here)
. Таким образом, abc(?=def)
будет соответствовать abc, а затем def.
Есть также отрицательные и положительные lookbehind - (?<!regex here)
и (?<=regex here)
соответственно
Следует отметить, что отрицательный lookahead имеет нулевую ширину. То есть, это не считается тем, что занимает какое-то пространство.
Таким образом, может показаться, что a(?=b)c
будет соответствовать "abc", но это не будет. Он будет соответствовать "a", а затем положительному взгляду с "b", но он не будет двигаться вперед в строку. Затем он попытается сопоставить "c" с "b", который не будет работать. Точно так же ^a(?=b)b$
будет соответствовать "ab", а не "abb", потому что обратные стороны имеют нулевую ширину (в большинстве реализаций регулярных выражений).
Дополнительная информация о этой странице
Ответ 4
Самый простой способ - полностью вывести отрицание из регулярного выражения:
if (!userName.matches("^([Ss]ys)?admin$")) { ... }
Ответ 5
Использование регулярного выражения, как вы описали, является простым способом (насколько мне известно). Если вам нужен диапазон, вы можете использовать [^ a-f].
Ответ 6
abc (?! def) не будет соответствовать abc по def. Таким образом, он будет соответствовать abce, abc, abck и т.д., что, если я не хочу, чтобы ни xyz не будет abc (?! (def) (xyz))???
У меня был тот же вопрос и нашел решение:
abc(?:(?!def))(?:(?!xyz))
Эти несчетные группы объединяются с помощью "И", поэтому это должно сделать трюк. Надеюсь, что это поможет.
Ответ 7
Регулярное выражение [^ (ab)] будет соответствовать, например, "ab ab ab ab", но не "ab", потому что оно будет соответствовать строке "a" или "b".
Какой язык/сценарий у вас есть? Вы можете вычесть результаты из исходного набора и просто совместить ab?
Если вы используете GNU grep и используете синтаксический анализ, используйте флаг "-v", чтобы инвертировать ваши результаты, возвращая все несоответствия. Другие инструменты регулярных выражений также имеют функцию return nonmatch.
Если я правильно понимаю, вы хотите все, кроме тех элементов, которые содержат "ab" где угодно.
Ответ 8
В этом случае я могу просто просто избегать регулярных выражений и идти с чем-то вроде:
if (StringToTest.IndexOf("ab") < 0)
//do stuff
Вероятно, это также будет намного быстрее (быстрый тест vs regexes выше показал, что этот метод занимает около 25% времени в методе regex). В общем, если я знаю точную строку, которую я ищу, я обнаружил, что регулярные выражения являются излишними. Поскольку вы знаете, что не хотите "ab", просто проверить, содержит ли строка эту строку, не используя регулярное выражение.
Ответ 9
Просто найдите "ab" в строке, затем отрицайте результат:
!/ab/.test("bamboo"); // true
!/ab/.test("baobab"); // false
Кажется, это проще и должно быть быстрее.