Регулярные выражения и отрицание целой группы символов [дубликат]

У нас была система, в которой много данных передавалось в виде JSON с сервера, а затем обрабатывалось через механизм шаблонов JavaScript на стороне клиента. В .Net 4.0 (может быть, даже 3.5 sp1, я не уверен), это можно сделать с помощью клиентских шаблонов .

Я бы предпочел передавать JSON, а не отправлять html. Всегда хорошо хранить данные и просматривать отдельно.

182
задан kmorris511 10 June 2009 в 07:11
поделиться

7 ответов

Используйте отрицательный просмотр вперед:

^(?!.*ab).*$

ОБНОВЛЕНИЕ: В комментариях ниже я заявил, что этот подход медленнее, чем тот, который приведен в ответе Питера . С тех пор я провел несколько тестов и обнаружил, что это действительно немного быстрее. Однако причина предпочесть этот метод другому не в скорости, а в простоте.

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

Для всех, кому интересно, я тестировал большой кусок текста Lorem Ipsum, подсчитывая количество строк, которые не содержат слова «quo».

177
ответ дан 23 November 2019 в 06:03
поделиться

Использование класса символов, такого как [^ 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
325
ответ дан 23 November 2019 в 06:03
поделиться

Использование регулярного выражения, как вы описали, является простым способом (насколько мне известно). Если вам нужен диапазон, вы можете использовать [^ af].

6
ответ дан 23 November 2019 в 06:03
поделиться

Да, это называется отрицательным просмотром вперед. Это выглядит так - (?! регулярное выражение здесь) . Итак, abc (?! Def) будет соответствовать abc , а не , за которым следует def. Таким образом, он будет соответствовать abce, abc, abck и т. Д.

Аналогичным образом есть положительный просмотр вперед - (? = Regex здесь) . Таким образом, abc (? = Def) будет соответствовать abc, за которым следует def.

Есть также отрицательный и положительный просмотр назад - (? и (? <= regex here) соответственно

Следует отметить, что отрицательный просмотр вперед имеет нулевую ширину. То есть, он не считается занятым.

Таким образом, может выглядеть, что a (? = B) c будет соответствовать «abc», но это не так. Это будет соответствовать ' a ', затем положительный просмотр вперед с' b ', но он не продвинется вперед в строке. Затем он попытается сопоставить «c» с «b», что не сработает. Точно так же ^ a (? = B) b $ будет соответствовать 'ab', а не 'abb', потому что поисковые запросы имеют нулевую ширину (в большинстве реализаций регулярных выражений).

Дополнительная информация о this стр.

55
ответ дан 23 November 2019 в 06:03
поделиться

Самый простой способ - полностью исключить отрицание из регулярного выражения:

if (!userName.matches("^([Ss]ys)?admin$")) { ... }
5
ответ дан 23 November 2019 в 06:03
поделиться

Регулярное выражение [^ (ab)] будет соответствовать, например, 'ab ab ab ab', но не 'ab', потому что оно будет соответствовать строке 'a' или 'b'.

Какой язык / сценарий соответствует у тебя есть? Можете ли вы вычесть результаты из исходного набора и просто сопоставить ab?

Если вы используете GNU grep и анализируете ввод, используйте флаг '-v', чтобы инвертировать результаты, возвращая все несовпадения. Другие инструменты регулярных выражений также имеют функцию «return nonmatch».

Если я правильно понимаю, вам нужно все, кроме тех элементов, которые где-либо содержат «ab».

4
ответ дан 23 November 2019 в 06:03
поделиться

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

if (StringToTest.IndexOf("ab") < 0)
  //do stuff

Это, вероятно, также будет намного быстрее (быстрый тест на регулярные выражения выше показал, что этот метод занимает около 25% времени метода регулярного выражения). В общем, если я знаю точную строку, которую ищу, я обнаружил, что регулярных выражений слишком много. Поскольку вы знаете, что не хотите "ab", просто проверить, содержит ли строка эту строку, без использования регулярного выражения.

3
ответ дан 23 November 2019 в 06:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: