为什么\ K似乎消耗了基础R的gsub中的一个字符

时间:2017-01-29 19:22:27

标签: r regex pcre

以下是一个示例字符串:'\\wa\\w\\K|\\w' 我希望我可以使用以下格式匹配'cad'以外的所有内容:gsub 如果我想替换不是gsub('\\wa\\w\\K|\\w', '', 'bcadefgh', perl = TRUE)的所有内容,我可以使用'cade',就像gsub(pattern = '\\wa\\w\\K|\\w', replacement = '', 'bcadefgh', perl = TRUE) # [1] "cade" 一样,但这会输出'\\wa\\w(*SKIP)(*F)|\\w'

ore

我的期望是\ K会在' d之后导致重置。在' cad'类似于ore::ore_subst(regex = '\\wa\\w\\K|\\w', replacement = '', text = 'bcadefgh', all = TRUE) # [1] "cad" ,因此,以下' e'应该匹配和替换。相反,在我看来,\ K正在消耗一个角色并在“e”之后重新开始匹配过程。我误解了这个吗?

regex101 (flavor: pcre),我得到了我的期望:除了' cad'匹配。

使用gsub包(Oniguruma正则表达式,而不是pcre),我也得到了预期的输出:

(?=\\w)

如果我回到\\w,但对于' a'后面的单词字符使用零宽度正向前瞻。而不是消费它(gsub('\\wa(?=\\w)\\K|\\w', '', 'bcadefgh', perl = TRUE) # [1] "cad" 而不是{{1}}):

{{1}}

我得到了所需的输出,但我不清楚为什么会这样。

这种行为的解释是什么?

1 个答案:

答案 0 :(得分:3)

Advancing After a Zero-Length Regex Match

  

R和PHP中的regexp函数基于PCRE,因此它们可以避免   像PCRE那样通过回溯卡在零长度的比赛上。   但是在R中搜索和替换的gsub()函数也会跳过   零长度匹配在前一个非零长度的位置   匹配结束,就像Python一样。

引擎在遇到零长度匹配方面有所不同。乍一看似乎在\s*|\S+之类的输入字符串上运行正如hello这样的正则表达式应该返回2个匹配项:

第一场比赛(h之前的零长度比赛):

¦h e l l o 
^

第二场比赛(全字):

hello 
>>>>>

人类就是这样想的。从正则表达式引擎的角度来看,情况并非如此。像PCRE这样的知名引擎会在最后一个字符后返回三个匹配项(前两个匹配项和\s*之间的零长度匹配项)但javascript或Python返回6.因为引擎会在零时跳过下一个非常直接的单个字符找到了长度匹配。

¦h¦e¦l¦l¦o¦ 
^ ^ ^ ^ ^ ^

所以引擎只用\s*部分来满足自己。 gsub以同样的方式运作。