RegEx用于查找重复的完整字符串(两级贪婪)

时间:2014-07-02 22:43:22

标签: regex regex-greedy non-greedy

我有一个(可能很复杂的)RegExp问题。 从模型生成文件的工具说我的模型使用了两次名称,但没有说明这是什么名字。 我知道所有有问题的名字都以“CK_”开头,后面跟着一些非空格。 我准备了这个测试文件:

CK_123abc
foo
CK_abc
CK_123abc
CK_199
bar
CK_177
bar
CK_188

正如您所见,“CK_123abc”出现两次。我想用RegExp捕获所有这些(如果还有更多)。到目前为止我得到了这个:(CK_ \ S *)。+ \ 1

这很好,并且符合以下文字:

CK_123abc
foo
CK_abc
CK_123abc

但它也匹配

CK_199
bar
CK_177
bar
CK_1

第二个不需要的匹配用于 CK_1 。 由于我的真实文档充满了这些“半串”匹配,我无法在数据中找到我的真实匹配(如此处的第一个)。 我认为(CK_ \ S *)由于某种原因并不贪心 - 或者整个正则表达式都是贪婪的。为了使用我的用例,(CK_ \ S *)必须首先匹配,然后在文档中稍后找到相同的匹配。

我正在使用Notepad ++(使用PCRE)。 “。”匹配“\ r”“\ n”

任何指针都受到高度赞赏。

4 个答案:

答案 0 :(得分:2)

如果您将(CK_\S*)锚定到空格字符,它将尽可能多地匹配:

(CK_\S*)\s.+\1

答案 1 :(得分:2)

使用此正则表达式:

(?s)(CK_\S+\b)(?=.*\1)

请参阅demo

<强>解释

  • (?s)激活DOTALL模式,允许点跨行匹配
  • (CK_\S+\b)将您的令牌捕获到第1组
  • 前瞻(?=.*\1)声称接下来是任意数量的字符,然后是第1组捕获的字符

<强>参考

答案 2 :(得分:2)

问题不在于量词的贪婪或懒惰,而在于正则表达式引擎的工作方式。当模式失败时,正则表达式引擎可以使用backtracking mechanism尝试其他可能性(直到模式成功,或直到没有更多可能性),并且字符串中的相同位置。

缓和此行为的唯一方法是在模式中添加更多约束(以限制可能性),如您在此处的几个答案中所见。

我们的想法是使用空格word boundariespossessive quantifiers检查名称的限制(左和右),而不要忘记为反向引用做同样的事情:

有空格:(?:\s|^)(CK_\S*)(?=\s.*(?<=\s)\1(?:\s|$)) (有点长,但可能是最防水的方式)

带有字边界的

\b(CK_\S*)\b(?=.*\b\1\b)

拥有量词和词边界\b(CK_\S*+)(?=.*\b\1\b)

注意:由于使用了点,您需要为所有模式打开单线模式。

答案 3 :(得分:0)

怎么样?     (CK _ [^ \ n]的*)。+ \ 1 所以你会把所有东西都带到新线上,这就是你想要的。