11

如何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

4 回答 4

8

您可以使用负前瞻

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

在线查看它:rubular

于 2013-02-06T23:12:21.130 回答
4

前瞻解决方案在某些情况下不起作用,您可以通过使用如下构造正确解决此问题,无需环顾四周:

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

即使某些单词是其他单词的子字符串,这也有效,如果您只想找到更大字符串的匹配子字符串(而不仅仅是匹配整个字符串),这也可以工作。

现场演示

如果之前已经匹配,它只是通过失败更改来工作,由(?(1)(?!)). (?(1)foo)是一个条件,foo如果 group1之前匹配,则将匹配。(?!)总是失败。

于 2013-02-06T23:49:51.743 回答
0

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

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

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

于 2013-02-06T23:50:27.130 回答
0

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

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

其中\1指的是捕获组的匹配(word1|word2|word3)

请注意,这假设word2不能通过将字符附加到 来形成word1,并且word3不能通过将字符附加到word1or来形成word2

于 2013-02-06T23:52:30.093 回答