Как отменить определенное слово в регулярном выражении?

Я знаю, что я могу отрицать группу символов, как в [^bar], но мне нужно регулярное выражение, где отрицание относится к конкретному слову - так что в моем примере, как я отрицаю фактический "bar", а не "any chars in bar"?

Ответ 1

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

^(?!.*bar).*$

Конструкция с отрицательным прогнозом - это пара круглых скобок, с открывающей скобкой, за которой следует знак вопроса и восклицательный знак. Внутри lookahead [есть любой шаблон регулярных выражений].

Ответ 2

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

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

Ответ 3

Следующее регулярное выражение будет делать то, что вы хотите (до тех пор, пока поддерживаются отрицательные lookbehinds и lookaheads), правильно подходящие вещи; единственная проблема заключается в том, что он соответствует отдельным символам (т.е. каждое совпадение - это один символ, а не все символы между двумя последовательными "барами" ), что может привести к высоким накладным расходам, если вы работаете с очень длинными строками.

b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]

Ответ 5

Я наткнулся на этот форум, пытаясь идентифицировать регулярное выражение для следующего английского заявления:

Учитывая входную строку, сопоставьте все, если только эта строка ввода не является "баром"; например, я хочу совместить "барьер" и "запрет", а также "foo".

Здесь regex я придумал

^(bar.+|(?!bar).*)$

Мой английский перевод регулярного выражения "соответствует строке, если она начинается с" bar ", и у нее есть хотя бы один другой символ, или если строка не начинается с" bar ".

Ответ 6

Решение:

^(?!.*STRING1|.*STRING2|.*STRING3).*$

xxxxxx ОК

xxxSTRING1xxx KO (желательно ли это)

xxxSTRING2xxx KO (желательно ли это)

xxxSTRING3xxx KO (желательно ли это)

Ответ 7

Принятый ответ хорош, но на самом деле является обходным процессом из-за отсутствия простого оператора выражения выражения выражений выражения в регулярных выражениях. Вот почему grep --invert-match завершает работу. Таким образом, в * nixes вы можете выполнить желаемый результат с помощью труб и второго регулярного выражения.

grep 'something I want' | grep --invert-match 'but not these ones'

Все еще обходной путь, но, возможно, легче запомнить.

Ответ 8

Я хочу дополнить принятый ответ и внести свой вклад в дискуссию своим поздним ответом.

@ChrisVanOpstal поделился этим руководством по регулярным выражениям, которое является отличным ресурсом для изучения регулярных выражений.

Тем не менее, это было действительно много времени, чтобы прочитать.

Я сделал шпаргалку для удобства мнемоники.

Эта ссылка основана на скобках [], () и {} ведущих каждый класс, и мне легко вспомнить.

Regex = {
 'single_character': ['[]', '.', {'negate':'^'}],
 'capturing_group' : ['()', '|', '\\', 'backreferences and named group'],
 'repetition'      : ['{}', '*', '+', '?', 'greedy v.s. lazy'],
 'anchor'          : ['^', '\b', '$'],
 'non_printable'   : ['\n', '\t', '\r', '\f', '\v'],
 'shorthand'       : ['\d', '\w', '\s'],
 }

Ответ 9

Просто подумал о чем-то другом, что можно было бы сделать. Это очень отличается от моего первого ответа, поскольку он не использует регулярные выражения, поэтому я решил сделать второй ответ.

Используйте свой язык выбора split() эквивалент метода в строке со словом, чтобы отрицать как аргумент для разделения. Пример использования Python:

>>> text = 'barbarasdbarbar 1234egb ar bar32 sdfbaraadf'
>>> text.split('bar')
['', '', 'asd', '', ' 1234egb ar ', '32 sdf', 'aadf']

Хорошая вещь в этом, по крайней мере, в Python (я не помню, была ли функциональность такой же, например, Visual Basic или Java), заключается в том, что она позволяет вам опознать, когда "bar" был повторен в строке из-за того, что пустые строки между "bar" s включены в список результатов (хотя пустая строка в начале происходит из-за наличия "бара" в начале строки). Если вы этого не хотите, вы можете просто удалить пустые строки из списка.

Ответ 10

У меня был список имен файлов, и я хотел исключить некоторые из них с таким поведением (Ruby):

files = [
  'mydir/states.rb',      # don't match these
  'countries.rb',
  'mydir/states_bkp.rb',  # match these
  'mydir/city_states.rb' 
]
excluded = ['states', 'countries']

# set my_rgx here

result = WankyAPI.filter(files, my_rgx)  # I didn't write WankyAPI...
assert result == ['mydir/city_states.rb', 'mydir/states_bkp.rb']

Здесь мое решение:

excluded_rgx = excluded.map{|e| e+'\.'}.join('|')
my_rgx = /(^|\/)((?!#{excluded_rgx})[^\.\/]*)\.rb$/

Мои предположения для этого приложения:

  • Строка, которая должна быть исключена, находится в начале ввода или сразу же после косой черты.
  • Допустимые строки заканчиваются на .rb.
  • Допустимые имена файлов не имеют символа . перед .rb.

Ответ 11

Извлечено из этого комментария bkDJ:

^(?!bar$).*

Приятным свойством этого решения является то, что можно четко отрицать (исключать) несколько слов:

^(?!bar$|foo$|banana$).*