题
寻找一些正则表达式帮助。我想设计一个与字符串匹配的表达式“富“ 或者 ”酒吧“,但不是两者都”富“ 和 ”酒吧"
如果我做类似的事情...
/((foo)|(bar))/
它将匹配“富巴”。不是我要找的。那么,如何才能仅在出现一个或另一个术语时才使正则表达式匹配呢?
谢谢!
解决方案
你可以使用一个正则表达式执行此操作,但我建议为了便于阅读,你会做类似的事情......
(/foo/ and not /bar/) || (/bar/ and not /foo/)
其他提示
如果您的正则表达式语言支持它,请使用否定的外观:
(?<!foo|bar)(foo|bar)(?!foo|bar)
这将匹配“foo”或“bar”不是紧接在“foo”之前或之后的“foo”。或“bar”,我认为这就是你想要的。
您的问题或示例中不清楚您尝试匹配的字符串是否可以包含其他令牌:“foocuzbar”。如果是这样,这种模式将不起作用。
以下是您的测试用例的结果(“true”表示在输入中找到了模式):
foo: true
bar: true
foofoo: false
barfoo: false
foobarfoo: false
barbar: false
barfoofoo: false
这将采用'foo'和'bar'但不是'foobar'而不是'blafoo'而不是'blabar':
/^(foo|bar)$/
^ = mark start of string (or line)
$ = mark end of string (or line)
这将采用'foo'和'bar'和'foo bar'和'bar-foo'而不是'foobar'而不是'blafoo'而不是'blabar':
/\b(foo|bar)\b/
\b = mark word boundry
您尚未指定除“foo”和“bar”之外的内容的行为,或者在没有另一个的情况下重复其中一个内容的行为。例如,应该“富d”或“野蛮人伊恩”匹配?
假设您想要匹配仅包含“foo”或“bar”的一个实例的字符串,但不是同时包含“foo”或“bar”的一个实例,也不是同一实例的多个实例,而不考虑字符串中的其他任何内容(即“food”匹配和“barbarian”不匹配),那么您可以使用正则表达式返回找到的匹配项数,并且只有在找到一个匹配项时才认为它成功。例如,在 Perl 中:
@matches = ($value =~ /(foo|bar)/g) # @matches now hold all foos or bars present
if (scalar @matches == 1) { # exactly one match found
...
}
如果允许同一目标的多次重复(即“野蛮人”匹配),则可以使用相同的通用方法,然后遍历匹配列表以查看匹配是否全部重复相同的文本,或者是否是其他选项也存在。
如果你想要一个真正的独家或者,我只是在代码中而不是在正则表达式中这样做。在Perl:
/foo/ xor /bar/
但是你的评论:
匹配:&quot; foo&quot;,&quot; bar&quot; nonmatches: &QUOT; foofoo&QUOT; &QUOT; barfoo&QUOT; &QUOT; foobarfoo&QUOT; &QUOT; BARBAR&QUOT; &QUOT; barfoofoo&QUOT;
表示您并不是真的在寻找独家或。你的意思是
“ / foo | bar /
只匹配一次吗?”
my $matches = 0;
while (/foo|bar/g) {
last if ++$matches > 1;
}
my $ok = ($matches == 1)
我知道这是一个迟到的条目,但只是为了帮助其他可能正在寻找的人:
(/b(?:(?:(?!foo)bar)|(?:(?!bar)foo))/b)
我会用这样的东西。它只是检查单词周围的空间,但是如果你使用 \ w
,你可以使用 \ b
或 \ B
来检查边框。这将匹配“ foo“或“ bar&quot;,所以显然你也必须更换空格,以防万一。 (假设你要更换任何东西。)
/\s((foo)|(bar))\s/
我认为这不能用一个正则表达式来完成。根据你所匹配的内容,边界可能会也可能不起作用。
我会分别匹配每个正则表达式,并对结果进行异或。
foo = re.search("foo", str) != None
bar = re.search("bar", str) != None
if foo ^ bar:
# do someting...
我试过Regex Coach反对:
x foo y
x bar y
x foobar y
如果我检查 g
选项,它确实匹配所有三个单词,因为它会在每次匹配后再次搜索。
如果您不想要此行为,则可以锚定表达式,例如仅匹配单词边界:
\b(foo|bar)\b
为问题提供更多背景信息(数据的外观)可能会给出更好的答案。
\b(foo)\b|\b(bar)\b
仅使用第一个捕获组。
使用单词边界,您可以得到单个单词......
me@home ~
$ echo "Where is my bar of soap?" | egrep "\bfoo\b|\bbar\b"
Where is my bar of soap?
me@home ~
$ echo "What the foo happened here?" | egrep "\bfoo\b|\bbar\b"
What the foo happened here?
me@home ~
$ echo "Boy, that sure is foobar\!" | egrep "\bfoo\b|\bbar\b"