1

我有一个(可能很复杂)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

4 回答 4

2

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

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

于 2014-07-02T22:50:09.650 回答
2

使用这个正则表达式:

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

演示

解释

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

参考

于 2014-07-02T22:50:21.397 回答
2

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

缓解这种行为的唯一方法是在您的模式中添加更多约束(以限制可能性),正如您在此处的几个答案中看到的那样。

这个想法是使用空格、单词边界所有格量词检查名称的限制(左和右) ,而不要忘记对反向引用执行相同的操作:

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

带字边界:\b(CK_\S*)\b(?=.*\b\1\b)

带有所有格量词和单词边界\b(CK_\S*+)(?=.*\b\1\b)

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

于 2014-07-02T23:33:41.080 回答
0

怎么样 (CK_[^\n]*).+\1 所以你会把一切都带到你想要的换行符之前。

于 2014-07-02T22:55:41.380 回答