我知道我可以在[^bar]
中否定一组字符,但我需要一个正则表达式,其中否定适用于特定的单词 - 所以在我的例子中我如何否定实际的"bar"
而不是"any chars in bar"
?
答案 0 :(得分:601)
答案 1 :(得分:59)
除非性能最受关注,否则通过第二遍传递结果通常更容易,跳过那些与您想要否定的词匹配的结果。
正则表达式通常意味着您正在编写脚本或某种低性能任务,因此找到一个易于阅读,易于理解且易于维护的解决方案。
答案 2 :(得分:44)
以下正则表达式会做你想要的(只要支持负面的后视和前瞻),正确匹配;唯一的问题是它匹配单个字符(即每个匹配是一个字符而不是两个连续“bar”之间的所有字符),如果你使用非常长的字符串,可能会导致高额开销。
b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]
答案 3 :(得分:42)
您可以使用negative look-ahead or look-behind:
^(?!.*?bar).*
^(.(?<!bar))*?$
或者只使用基础知识:
^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$
这些都匹配任何不包含bar
的内容。
答案 4 :(得分:29)
我在尝试识别以下英语声明的正则表达式时遇到了这个论坛帖子:
给定一个输入字符串,匹配所有内容 ,除非此输入字符串恰好是'bar';例如,我想匹配'barrier'和'disbar'以及'foo'。
这是我提出的正则表达式
^(bar.+|(?!bar).*)$
正则表达式的英文翻译是“匹配字符串,如果它以'bar'开头,并且它至少有一个其他字符,或者字符串不以'bar'开头。
答案 5 :(得分:28)
<强>解决方案:强>
^(?!.*STRING1|.*STRING2|.*STRING3).*$
xxxxxx 确定
xxxSTRING1xxx KO(是否需要)
xxxSTRING2xxx KO(是否需要)
xxxSTRING3xxx KO(是否需要)
答案 6 :(得分:8)
接受的答案很好,但实际上是在正则表达式中缺少一个简单的子表达式否定运算符。这就是grep --invert-match
退出的原因。因此,在* nixes中,您可以使用管道和第二个正则表达式来完成所需的结果。
grep 'something I want' | grep --invert-match 'but not these ones'
仍然是一种解决方法,但也许更容易记住。
答案 7 :(得分:3)
我希望补充已接受的答案,并以我最近的答案为讨论作出贡献。
@ChrisVanOpstal分享了this 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'],
}
答案 8 :(得分:1)
想到可以做的其他事情。这与我的第一个答案非常不同,因为它不使用正则表达式,所以我决定做第二个答案。
使用您选择的语言split()
方法等效于字符串,并将单词取消作为拆分内容的参数。使用Python的一个例子:
>>> text = 'barbarasdbarbar 1234egb ar bar32 sdfbaraadf'
>>> text.split('bar')
['', '', 'asd', '', ' 1234egb ar ', '32 sdf', 'aadf']
这样做的好处,至少在Python中是这样的(我不记得功能在Visual Basic或Java中是否相同)是它让你间接地知道“bar”由于“bar”之间的空字符串包含在结果列表中(尽管开头的空字符串是由于字符串开头有“bar”),因此在字符串中重复了这一点。如果您不想这样,您只需从列表中删除空字符串即可。
答案 9 :(得分:1)
我有一个文件名列表,我想用这种行为(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
个字符。答案 10 :(得分:0)
从this comment提取到bkDJ:
class MyFormSerializer(serializers.ModelSerializer):
class Meta:
model = MyForm
fields = (..., 'animals')
animals = CustomMultipleChoiceField(choices=ANIMAL)
此解决方案的一个不错的特性是可以明确否定(排除)多个单词:
^(?!bar$).*
答案 11 :(得分:0)
如果您确实不想匹配bar
这是一个单词,则:
^(?!.*\bbar\b).*$
以上内容将匹配单词边界上不包含bar
的任何字符串,也就是说,与非单词字符分开的字符串。但是,除非使用正确的正则表达式标志,否则以上模式中使用的句点/点(.
)将不匹配换行符:
^(?s)(?!.*\bbar\b).*$
或者:
^(?!.*\bbar\b)[\s\S]*$
我们正在寻找不是空格还是非空格的任何字符,而不是使用任何特殊标志。那应该覆盖所有字符。
但是,如果我们想匹配可能包含bar
而不是特定单词bar
的单词怎么办?
(?!\bbar\b)\b\[A-Za-z-]*bar[a-z-]*\b
(?!\bbar\b)
断言下一个输入不是bar
在单词边界上。\b\[A-Za-z-]*bar[a-z-]*\b
匹配包含bar
的单词边界上的任何单词。