RegEx - Исключить совпадающие шаблоны

У меня есть следующие шаблоны, которые нужно исключить.

make it cheaper
make it cheapere
makeitcheaper.com.au
makeitcheaper
making it cheaper
www.make it cheaper
ww.make it cheaper.com

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

mak(e|ing) ?it ?cheaper

Вышеуказанный шаблон соответствует всем перечисленным строкам. Теперь я хочу, чтобы он соответствовал всему остальному. Как это сделать?

Из поиска, кажется, мне нужно что-то вроде негативного взгляда/оглянуться назад. Но я действительно не понимаю. Может ли кто-нибудь указать мне в правильном направлении?

Ответ 1

Вы можете просто положить его в негативный прогноз вперед следующим образом:

(?!mak(e|ing) ?it ?cheaper)

Так же, как будто это не сработает, поскольку, если вы выполните matches 1 это не будет соответствовать, поскольку вы просто смотрите вперед, вы на самом деле не соответствуете ничего, и если вы выполните find 1 он будет соответствовать много раз, так как вы можете начать с большого количества мест в строке, где следующие символы не соответствуют указанному выше.

Чтобы исправить это, в зависимости от того, что вы хотите сделать, у нас есть 2 варианта:

  • Если вы хотите исключить все строки точно, то один из них (т.е. "сделать его более дешевым" не исключен), проверьте для начала (^) и конец ($) строки:

    ^(?!mak(e|ing) ?it ?cheaper$).*
    

    .* (нуль или более wild-cards) - это фактическое совпадение. Отрицательный контроль вперед проверяется от первого символа.

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

    ^((?!mak(e|ing) ?it ?cheaper).)*$
    

    Альтернативой является добавление wild-cards в начало вашего ожидания (т.е. исключение всех строк, которые с начала строки содержат что угодно, а затем ваш шаблон), но в настоящее время я не вижу никаких преимуществ к этому (произвольный внешний вид длины также менее вероятен для поддержки любого данного инструмента):

    ^(?!.*mak(e|ing) ?it ?cheaper).*
    

Из-за ^ и $ либо выполнение find, либо matches будет работать для любого из вышеперечисленных (хотя в случае matches ^ является необязательным и, в случае find .* за пределами внешнего вида необязательно).


1: Хотя они не могут быть вызваны, многие языки имеют функции, эквивалентные matches и find с регулярным выражением.


Выше был строго-регулярный ответ на этот вопрос.

Лучшим подходом может быть привязка к исходному регулярному выражению (mak(e|ing) ?it ?cheaper) и посмотреть, можете ли вы скрыть совпадения непосредственно с инструментом или языком, который вы используете.

В Java, например, это включает в себя выполнение if (!string.matches(originalRegex)) (обратите внимание на !, который отрицает возвращаемое логическое значение) вместо if (string.matches(negLookRegex)).

Ответ 2

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

(?!.*mak(e|ing) ?it ?cheaper)

И, возможно, немного более гибкая:

(?!.*mak(e|ing) *it *cheaper)

На всякий случай имеется более одного места.