Я знаю, что я могу отрицать группу символов, как в [^bar]
, но мне нужно регулярное выражение, где отрицание относится к конкретному слову - так что в моем примере, как я отрицаю фактический "bar"
, а не "any chars in bar"
?
Отличный способ сделать это - использовать негативный взгляд:
^(?!.*bar).*$
Конструкция негативного прогноза представляет собой пару круглых скобок с открывающей скобкой, за которой следует вопросительный знак и восклицательный знак. Внутри lookahead [является любым шаблоном регулярного выражения].
Если производительность не вызывает особой озабоченности, часто проще просто выполнить свои результаты через второй проход, пропуская те, которые соответствуют словам, которые вы хотите скрыть.
Регулярные выражения обычно означают, что вы все равно выполняете скрипты или какую-то низкопроизводительную задачу, поэтому находите решение, которое легко читать, легко понять и легко поддерживать.
Следующее регулярное выражение будет делать то, что вы хотите (до тех пор, пока поддерживаются отрицательные lookbehinds и lookaheads), правильно подходящие вещи; единственная проблема заключается в том, что он соответствует отдельным символам (т.е. каждое совпадение - это один символ, а не все символы между двумя последовательными "барами" ), что может привести к высоким накладным расходам, если вы работаете с очень длинными строками.
b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]
Вы можете использовать негативный внешний вид или внешний вид:
^(?!.*?bar).*
^(.(?<!bar))*?$
Или используйте только основы:
^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$
Все они соответствуют всем, что не содержит bar
.
Я наткнулся на этот форум, пытаясь идентифицировать регулярное выражение для следующего английского заявления:
Учитывая входную строку, сопоставьте все, если только эта строка ввода не является "баром"; например, я хочу совместить "барьер" и "запрет", а также "foo".
Здесь regex я придумал
^(bar.+|(?!bar).*)$
Мой английский перевод регулярного выражения "соответствует строке, если она начинается с" bar ", и у нее есть хотя бы один другой символ, или если строка не начинается с" bar ".
Решение:
^(?!.*STRING1|.*STRING2|.*STRING3).*$
xxxxxx ОК
xxxSTRING1xxx KO (желательно ли это)
xxxSTRING2xxx KO (желательно ли это)
xxxSTRING3xxx KO (желательно ли это)
Принятый ответ хорош, но на самом деле является обходным процессом из-за отсутствия простого оператора выражения выражения выражений выражения в регулярных выражениях. Вот почему grep --invert-match
завершает работу. Таким образом, в * nixes вы можете выполнить желаемый результат с помощью труб и второго регулярного выражения.
grep 'something I want' | grep --invert-match 'but not these ones'
Все еще обходной путь, но, возможно, легче запомнить.
Я надеюсь дополнить ответ
Как уточнил Крис Regex Tutorial - лучший ресурс для обучения регулярному выражению.
Однако он действительно потреблял время для чтения.
Я делаю чит-коды для удобства мнемоники. []
, ()
, {}
ведущие к каждому классу, который легко вспомнить.
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'],
}
У меня был список имен файлов, и я хотел исключить некоторые из них с таким поведением (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
.Просто подумал о чем-то другом, что можно было бы сделать. Это очень отличается от моего первого ответа, поскольку он не использует регулярные выражения, поэтому я решил сделать второй ответ.
Используйте свой язык выбора split()
эквивалент метода в строке со словом, чтобы отрицать как аргумент для разделения. Пример использования Python:
>>> text = 'barbarasdbarbar 1234egb ar bar32 sdfbaraadf'
>>> text.split('bar')
['', '', 'asd', '', ' 1234egb ar ', '32 sdf', 'aadf']
Хорошая вещь в этом, по крайней мере, в Python (я не помню, была ли функциональность такой же, например, Visual Basic или Java), заключается в том, что она позволяет вам опознать, когда "bar" был повторен в строке из-за того, что пустые строки между "bar" s включены в список результатов (хотя пустая строка в начале происходит из-за наличия "бара" в начале строки). Если вы этого не хотите, вы можете просто удалить пустые строки из списка.