Соответствует всем, кроме указанных строк

120

Я знаю, что следующее регулярное выражение будет соответствовать «красному», «зеленому» или «синему».

red|green|blue

Есть ли простой способ сопоставить все, кроме нескольких указанных строк?

Альфред
источник
1
Не все разновидности регулярных выражений могут это сделать. В какой среде вы работаете? Ява? Perl? .СЕТЬ? Некоторая библиотека регулярных выражений C / C ++? РСУБД?
FrustratedWithFormsDesigner
8
Вы не говорите, чего хотите, но можете просто изменить смысл операции «сопоставления». Это не поможет вам, если вы пытаетесь выполнить извлечение на несовпадающих частях, но чтобы проверить, отсутствует ли исключенная строка, она будет работать: if (!s.match(/red|green|blue/)) ... Примечание: я знаю, что OP не указывает, какой язык / фреймворк, поэтому предыдущее следует рассматривать как общий, а не предписывающий пример.
tvanfosson 08

Ответы:

154

Если вы хотите убедиться, что строка не является ни красной, ни зеленой, ни синей, ответ на этот вопрос - каски. Однако часто требуется убедиться, что линия нигде не содержит красного, зеленого или синего цветов. Для этого закрепите регулярное выражение ^и включите его .*в отрицательный прогноз:

^(?!.*(red|green|blue))

Также предположим, что вам нужны строки, содержащие слово «двигатель», но без этих цветов:

^(?!.*(red|green|blue)).*engine

Вы можете подумать, что можете разложить на .*начало регулярного выражения:

^.*(?!red|green|blue)engine     # Does not work

но ты не можешь. У вас должны быть оба экземпляра, .*чтобы он работал.

Уэйн Конрад
источник
48

Зависит от языка, но, как правило, есть отрицательные утверждения, которые вы можете вставить так:

(?!red|green|blue)

(Спасибо за исправление синтаксиса, приведенное выше верно для Java и Perl, YMMV)

Каски
источник
2
@caskey, Полный ответ - комбинация моего и вашего. Если вы хотите объединить их вместе, я удалю свой.
Уэйн Конрад
14
Этот ответ был бы намного полезнее, если бы вы его немного объяснили. Например: что делать? и "!" значит? Зачем нужны группы захвата?
Lii
Это тоже правильный Python.
Джо Морнин
просто использовал это с библиотекой RegEx Delphi, и это работает только так: ^ (?! красный | зеленый | синий). Также верно для тестирования на regex101.com . Так это опечатка без символа ^ или это действительно так в Java / Perl / Python ..?
Питер
33

Соответствие чему угодно, кроме заданных строк

Если вы хотите сопоставить всю строку, где вы хотите сопоставить все, кроме определенных строк, вы можете сделать это следующим образом:

^(?!(red|green|blue)$).*$

Это говорит о том, что сопоставление начинается с начала строки, где оно не может начинаться и заканчиваться красным, зеленым или синим цветом, и сопоставлять что-либо еще с концом строки.

Вы можете попробовать это здесь: https://regex101.com/r/rMbYHz/2

Обратите внимание, что это работает только с механизмами регулярных выражений, которые поддерживают отрицательный просмотр вперед .

Сэм
источник
23

Вам не нужен отрицательный взгляд вперед. Есть рабочий пример:

/([\s\S]*?)(red|green|blue|)/g

Описание:

  • [\s\S] - соответствовать любому персонажу
  • * - совпадение от 0 до безлимитного из предыдущей группы
  • ? - совпадать как можно меньше
  • (red|green|blue|) - сопоставьте одно из этих слов или ничего
  • g - повторить узор

Пример:

whiteredwhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredwhiteredgreenbluewhiteredwhiteredwhiteredwhiteredwhiteredredgreenredgreenredgreenredgreenredgreenbluewhiteredbluewhiteredbluewhiteredbluewhiteredbluewhiteredwhite

Будет:

whitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhitewhite

Попробуй это: regex101.com

КГ
источник
4
Вы можете значительно уменьшить количество шагов, заменив [\ s \ S] точкой. Я был очень смущен, почему, казалось бы, каждый другой пример захватывает каждое слово индивидуально. Этот способ требует немного большего количества шагов регулярного выражения, но требует гораздо меньше постобработки.
Затрониум
3
но при этом не выполняется сопоставление (проверка текста), он просто удаляет указанный текст во время подстановки.
Marek R
Это решение не будет выводить последний фрагмент текста после известных слов. Так что сравнивать скорость не нужно, это неправильно.
Виктор Стрибичев,
@ WiktorStribiżew исправлено.
hlcs
10

У меня был тот же вопрос, предложенные решения почти работали, но у них была проблема. В конце концов, я использовал регулярное выражение:

^(?!red|green|blue).*

Я тестировал его в Javascript и .NET.

. * не следует помещать внутри отрицательного просмотра вперед следующим образом: ^ (?!. * red | green | blue), иначе поведение первого элемента будет отличаться от остальных (т.е. "anotherred" не будет соответствовать, пока " anothergreen "будет)

Durden81
источник
3

Соответствие любому тексту, кроме тех, которые соответствуют шаблону, обычно достигается разделением строки с помощью шаблона регулярного выражения .

Примеры :

  • - Regex.Split(text, @"red|green|blue")или, чтобы избавиться от пустых значений Regex.Split(text, @"red|green|blue").Where(x => !string.IsNullOrEmpty(x))(см. демонстрацию )
  • - Regex.Split(text, "red|green|blue")или, чтобы удалить пустые элементы Regex.Split(text, "red|green|blue").Where(Function(s) Not String.IsNullOrWhitespace(s))(см. демонстрацию или эту демонстрацию, где поддерживается LINQ)
  • - text.split(/red|green|blue/)(здесь нет необходимости использовать gмодификатор!) (чтобы избавиться от пустых значений, используйте text.split(/red|green|blue/).filter(Boolean)), см. демонстрацию
  • - text.split("red|green|blue"), или - чтобы сохранить все конечные пустые элементы - используйте text.split("red|green|blue", -1), или чтобы удалить все пустые элементы, используйте дополнительный код для их удаления (см. демонстрацию )
  • - Подобно Java, text.split(/red|green|blue/)чтобы использовать все конечные элементы text.split(/red|green|blue/, -1)и удалить все пустые элементы text.split(/red|green|blue/).findAll {it != ""})(см. Демонстрацию )
  • - text.split(Regex("red|green|blue"))или, чтобы удалить пустые элементы, используйте text.split(Regex("red|green|blue")).filter{ !it.isBlank() }, см. демонстрацию
  • - text.split("red|green|blue"), или чтобы оставить все конечные пустые элементы, используйте text.split("red|green|blue", -1)и, чтобы удалить все пустые элементы, используйте text.split("red|green|blue").filter(_.nonEmpty)(см. демонстрацию )
  • - text.split(/red|green|blue/), чтобы избавиться от пустых значений, используйте .split(/red|green|blue/).reject(&:empty?)(и чтобы получить как начальные, так и конечные пустые элементы, используйте -1в качестве второго аргумента .split(/red|green|blue/, -1)) (см. демонстрацию )
  • - my @result1 = split /red|green|blue/, $text;, или со всеми конечными пустыми элементами, my @result2 = split /red|green|blue/, $text, -1;или без пустых элементов my @result3 = grep { /\S/ } split /red|green|blue/, $text;(см. демонстрацию )
  • - preg_split('~red|green|blue~', $text)или preg_split('~red|green|blue~', $text, -1, PREG_SPLIT_NO_EMPTY)чтобы не выводить пустые элементы (см. демонстрацию )
  • - re.split(r'red|green|blue', text)или, чтобы удалить пустые элементы list(filter(None, re.split(r'red|green|blue', text)))(см. демонстрацию )
  • - Используйте regexp.MustCompile("red|green|blue").Split(text, -1), а если вам нужно удалить пустые элементы, используйте этот код . См. Демонстрацию Go .

ПРИМЕЧАНИЕ . Если шаблоны содержат группы захвата , функции / методы разделения регулярных выражений могут вести себя по-разному, также в зависимости от дополнительных параметров. Тогда обратитесь к соответствующей документации по методу разделения.

Виктор Стрибьев
источник
0

Все, кроме слова "красный"

var href = '(text-1) (red) (text-3) (text-4) (text-5)';

var test = href.replace(/\((\b(?!red\b)[\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Все, кроме слова "красный"

var href = '(text-1) (frede) (text-3) (text-4) (text-5)';

var test = href.replace(/\(([\s\S]*?)\)/g, testF); 

function testF(match, p1, p2, offset, str_full) {
  p1 = p1.replace(/red/g, '');
  p1 = "-"+p1+"-";
  return p1;
}

console.log(test);

Юрий Светлов
источник