Збігайте все, крім вказаних рядків


119

Я знаю, що наступний регулярний вираз відповідає «червоному», «зеленому» або «синьому».

red|green|blue

Чи існує прямий спосіб його узгодження з усім, крім кількох вказаних рядків?


1
Не всі аромати регулярних виразів можуть це зробити. У якому середовищі ти працюєш? Java? Perl? .NET? Якась бібліотека регулярних виразів C / C ++? RDBMS?
FrustratedWithFormsDesigner

8
Ви не говорите, чого хочете, але можете просто перевернути сенс операції "відповідність". Це не допоможе вам, якщо ви намагаєтеся витягнути невідповідні частини, але протестувати, чи немає виключеного рядка, він би працював: if (!s.match(/red|green|blue/)) ... Примітка: Я знаю, що в ОП не вказано, що мова / рамка, так попередній слід вважати загальним прикладом, а не рецептурним.
tvanfosson

Відповіді:


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
Ця відповідь була б набагато кориснішою, якщо ви її трохи пояснили. Наприклад: Що робити "?" і "!" означає? Для чого потрібні групи захоплення?
Лій

Це також дійсний 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
але це не відповідає (перевірка тексту), воно просто видаляє вказаний текст під час заміни.
Марек Р

Це рішення не виведе остаточний фрагмент тексту після відомих слів. Отже, немає потреби в порівнянні швидкості, це просто неправильно.
Wiktor Stribiżew

@ WiktorStribiżew виправлено.
hlcs

10

У мене було те саме питання, запропоновані рішення майже працювали, але вони мали деяке питання. Зрештою, я використовував регулярний вираз:

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

Я перевірив це у Javascript та .NET.

. * не слід розміщувати всередині негативної позиції на зразок цього: ^ (?!. * червоний | зелений | синій), або це призведе до того, що перший елемент поводитиметься відмінним від решти (тобто "інший" не збігається, поки " інший зелений "би)


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), і якщо вам потрібно видалити порожні предмети, використовуйте цей код . Дивіться Перейти демо .

ПРИМІТКА . Якщо шаблони містять групи захоплення , функції / методи повторного вираження можуть поводитися по-різному, також залежно від додаткових параметрів. Тоді зверніться до відповідної документації про метод розділення.


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);

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.