正则表达式'或'运算符避免重复

时间:2013-02-06 23:10:41

标签: c# .net regex

如何在不允许重复的情况下使用or运算符?换句话说,正则表达式:

(word1|word2|word3)+

将匹配word1word2,但也会匹配我不想要的word1word1,因为word1正在重复。我怎样才能避免重复?

总之,我希望以下主题与之匹配:

word1word2word3
word1
word2
word3word2

注意所有这些都匹配,因为没有重复。我希望以下主题失败:

word1word2word1
word2word2
word3word1word2word2

修改

感谢@Mark我知道:

(?xi)

(?:  
        (?<A>word1|word2)(?!  .*  \k<A> )      # match for word1 or word2 but make sure that if you capture it it does not follow what it was just captured
    |   (?<B>word3|word4)(?!  .*  \k<B> )
)+

因为我有兴趣看看是否在A组或B组中捕获了某些东西。

4 个答案:

答案 0 :(得分:7)

您可以使用negative lookaheads

^(?:word1(?!.*word1)|word2(?!.*word2)|word3(?!.*word3))+$

查看在线工作:rubular

答案 1 :(得分:4)

前瞻性解决方案在多种情况下都不起作用,你可以通过使用这样的结构正确地解决这个问题,而无需看似:

(?:(?(1)(?!))(word1)|(?(2)(?!))(word2)|(?(3)(?!))(word3))+

即使某些单词是其他单词的子串,如果你只想找到一个较大字符串的匹配子串(并且不仅匹配整个字符串),这也会有效。

Live demo

如果之前已经匹配,由(?(1)(?!))完成,它只会失败。 (?(1)foo)是有条件的,如果小组foo之前已匹配,则会与1匹配。 (?!)总是失败。

答案 2 :(得分:0)

Byers的解决方案编码太硬,并且在字母增加后变得相当麻烦。为什么不简单地让正则表达式寻找重复匹配?

([^\d]+\d)+(?=.*\1)

如果匹配,则该匹配表示在模式中发现重复。如果匹配不起作用,则您拥有一组有效的数据。

答案 3 :(得分:0)

您可以使用包含后引用的否定前瞻:

^(?:(word1|word2|word3)(?!.*\1))+$

其中\1表示捕获组(word1|word2|word3)的匹配。

请注意,这假定word2无法通过向word1附加字符来形成,word3无法通过将字符附加到word1word2来形成{{1}}