【发布时间】:2010-11-17 10:30:10
【问题描述】:
我知道我可以像[^bar] 那样否定一组字符,但我需要一个正则表达式,其中否定适用于特定单词 - 所以在我的示例中,我如何否定实际的bar,而不是“任何字符”在酒吧”?
【问题讨论】:
标签: regex
我知道我可以像[^bar] 那样否定一组字符,但我需要一个正则表达式,其中否定适用于特定单词 - 所以在我的示例中,我如何否定实际的bar,而不是“任何字符”在酒吧”?
【问题讨论】:
标签: regex
您可以使用negative look-ahead or look-behind:
^(?!.*?bar).*
^(.(?<!bar))*?$
或者只使用基础知识:
^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$
这些都匹配任何不包含bar的内容。
【讨论】:
下面的正则表达式会做你想做的事(只要支持负后瞻和前瞻),正确匹配事物;唯一的问题是它匹配单个字符(即每个匹配是单个字符,而不是两个连续“条”之间的所有字符),如果您使用非常长的字符串,可能会导致高开销。
b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]
【讨论】:
/(?:(?!bar).)*/g on foobar 返回foo AND ar。
【讨论】:
grep -v bar 怎么样 :)
只是想到了可以做的其他事情。和我的第一个答案很不一样,因为它不使用正则表达式,所以我决定做第二个答案。
在字符串上使用您选择的语言的 split() 等效方法,将单词 to negate 作为拆分内容的参数。使用 Python 的示例:
>>> text = 'barbarasdbarbar 1234egb ar bar32 sdfbaraadf'
>>> text.split('bar')
['', '', 'asd', '', ' 1234egb ar ', '32 sdf', 'aadf']
这样做的好处是,至少在 Python 中(我不记得在 Visual Basic 或 Java 中功能是否相同),它可以让您间接知道“bar”由于“bar”之间的空字符串包含在结果列表中(尽管开头的空字符串是由于字符串开头有一个“bar”),因此在字符串中重复。如果你不想这样,你可以简单地从列表中删除空字符串。
【讨论】:
我在尝试为以下英文语句识别正则表达式时遇到了这个论坛主题:
给定一个输入字符串,匹配所有内容 除非这个输入字符串正好是'bar';例如,我想匹配 'barrier' 和 'disbar' 以及 'foo'。
这是我想出的正则表达式
^(bar.+|(?!bar).*)$
我对正则表达式的英文翻译是“匹配字符串,如果它以'bar'开头并且它至少有一个其他字符,或者如果字符串不以'bar'开头。
【讨论】:
^(?!bar$).* 与此匹配(除 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 之前没有. 字符。【讨论】:
接受的答案很好,但对于正则表达式中缺少简单的子表达式否定运算符确实是一种解决方法。这就是grep --invert-match 退出的原因。因此,在 *nixes 中,您可以使用管道和第二个正则表达式来实现所需的结果。
grep 'something I want' | grep --invert-match 'but not these ones'
仍然是一种解决方法,但可能更容易记住。
【讨论】:
invert match 选项。它仅限于 unix grep 吗?
解决方案:
^(?!.*STRING1|.*STRING2|.*STRING3).*$
xxxxxx 好的
xxxSTRING1xxx KO(是否要)
xxxSTRING2xxx KO(是否要)
xxxSTRING3xxx KO(是否要)
【讨论】:
我希望用我迟到的答案来补充已接受的答案并为讨论做出贡献。
@ChrisVanOpstal 分享了@987654321@,这是学习正则表达式的绝佳资源。
但是,通读一遍真的很费时间。
为了方便记忆,我做了一个备忘单。
这个参考是基于大括号[]、()和{}领导每个班级,我觉得很容易回忆。
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'],
}
【讨论】:
【讨论】:
.*?
如果它真的是一个你不想匹配的单词,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 的单词边界上的任何单词。【讨论】: