我知道我可以否定[^bar]中的一组字符,但我需要一个正则表达式,其中否定适用于特定单词-所以在我的示例中,我如何否定一个实际的条,而不是“条中的任何字符”?
当前回答
我有一个文件名列表,我想通过这种行为(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”),所以它可以间接地让您知道字符串中何时重复了“bar”。如果您不想这样做,只需从列表中删除空字符串即可。
解决方案:
^(?!.*STRING1|.*STRING2|.*STRING3).*$
xxxxxx正常
xxxSTRING1xxx KO(是否需要)
xxxSTRING2xxx KO(是否需要)
xxxSTRING3xxx KO(是否需要)
我想补充已接受的答案,并用我迟来的答案为讨论作出贡献。
@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'],
}
除非性能是最重要的,否则通常只需通过第二次测试来运行结果,跳过那些与您想要否定的单词相匹配的单词就更容易了。
正则表达式通常意味着您正在执行脚本编写或某种低性能任务,因此请找到一个易于阅读、易于理解和易于维护的解决方案。
我有一个文件名列表,我想通过这种行为(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之前的字符。