独家或正则表达

时间:2008-10-29 15:07:32

标签: regex xor

寻找一些正则表达式的帮助。 我想设计一个匹配字符串的表达式“ foo ”或“ bar ”,但不能同时设置“ foo ”AND“

如果我做某事......

/((foo)|(bar))/

它将匹配“ foobar ”。不是我想要的。那么,如果只有一个术语或另一个术语出现,我怎样才能使正则表达式匹配?

谢谢!

13 个答案:

答案 0 :(得分:32)

这就是我使用的:

/^(foo|bar){1}$/

请参阅:http://www.regular-expressions.info/quickstart.html重复

答案 1 :(得分:16)

如果您的正则表达式语言支持它,请使用negative lookaround

(?<!foo|bar)(foo|bar)(?!foo|bar)

这将匹配“foo”或“bar”,它们不会紧跟在“foo”或“bar”之前或之后,我认为这就是你想要的。

从您的问题或示例中可以看出,您尝试匹配的字符串是否包含其他令牌:“foocuzbar”。如果是这样,这种模式将不起作用。

以下是您的测试用例的结果(“true”表示在输入中找到了模式):

foo: true
bar: true
foofoo: false
barfoo: false
foobarfoo: false
barbar: false
barfoofoo: false

答案 2 :(得分:9)

你可以使用一个正则表达式执行此操作,但我建议为了便于阅读,你会做类似的事情......

(/foo/ and not /bar/) || (/bar/ and not /foo/)

答案 3 :(得分:6)

这将采用'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

答案 4 :(得分:3)

您没有指定关于“foo”和“bar”以外的内容的行为,或者在没有另一个的情况下重复一个内容。例如,“ foo d”或“ barbar ian”应该匹配吗?

假设您想要匹配仅包含“foo”或“bar”的一个实例的字符串,而不是两者都匹配,而不是同一个实例的多个实例,而不考虑字符串中的任何其他内容(即“食物” “匹配和”野蛮人“不匹配),那么您可以使用正则表达式返回找到的匹配数,只有在找到一个匹配项时才认为它成功。例如,在Perl:

@matches = ($value =~ /(foo|bar)/g)  # @matches now hold all foos or bars present
if (scalar @matches == 1) {          # exactly one match found
  ...
}

如果允许同一目标的多次重复(即“野蛮人”匹配),则可以使用相同的一般方法然后遍历匹配列表以查看匹配是否都是相同文本的重复或者是否另一种选择也存在。

答案 5 :(得分:2)

你可能想考虑一下?条件测试。

(?(?=regex)then|else)

Regular Expression Conditionals

答案 6 :(得分:1)

如果你想要一个真正的独家或者,我只是在代码中而不是在正则表达式中这样做。在Perl:

/foo/ xor /bar/

但是你的评论:

  

匹配:“foo”,“bar”不匹配:   “foofoo”“barfoo”“foobarfoo”“barbar”   “barfoofoo”

表示您并不是真的在寻找独家或。你的意思是 “/foo|bar/只匹配一次吗?”

my $matches = 0;
while (/foo|bar/g) {
  last if ++$matches > 1;
}

my $ok = ($matches == 1)

答案 7 :(得分:1)

我知道这是一个迟到的条目,但只是为了帮助其他可能正在寻找的人:

(/b(?:(?:(?!foo)bar)|(?:(?!bar)foo))/b)

答案 8 :(得分:0)

我会用这样的东西。它只是检查单词周围的空间,但如果您使用\b,则可以使用\B\w来检查边框。这将匹配“foo”或“bar”,所以显然你也必须更换空格,以防万一。 (假设你要更换任何东西。)

/\s((foo)|(bar))\s/

答案 9 :(得分:0)

我认为这不能用一个正则表达式来完成。根据你所匹配的内容,边界可能会也可能不起作用。

我会分别匹配每个正则表达式,并对结果进行异或。

foo = re.search("foo", str) != None
bar = re.search("bar", str) != None
if foo ^ bar:
    # do someting...

答案 10 :(得分:0)

我试过Regex Coach反对:

x foo y
x bar y
x foobar y

如果我检查g选项,确实它匹配所有三个单词,因为它会在每次匹配后再次搜索。
如果您不想要此行为,则可以锚定表达式,例如仅匹配单词边界:

\b(foo|bar)\b

为问题提供更多背景信息(数据的外观)可能会给出更好的答案。

答案 11 :(得分:0)

\b(foo)\b|\b(bar)\b

仅使用第一个capture group

答案 12 :(得分:0)

使用单词边界,您可以得到单个单词......

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"