我有一个(可能很复杂的)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”。
任何指针都受到高度赞赏。
答案 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 boundaries或possessive 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 所以你会把所有东西都带到新线上,这就是你想要的。