使用\ K和lookahead不能按预期工作

时间:2018-01-22 06:42:46

标签: ruby regex regex-lookarounds

我在https://ruby-doc.org/core-2.5.0/Regexp.html中没有找到\K的提及,但它似乎已实现(Support of \K in regex) - 我的版本是2.5.0p0

但是,对于此示例,它无法正常工作(基于perl的行为):

$ # expected behavior, replace empty fields with NA where comma is separator
$ echo ',a,,,b,' | ruby -pe 'gsub(/(?<=^|,)(?=,|$)/, "NA")'
NA,a,NA,NA,b,NA
$ # why a,,,b is not changing to a,NA,NA,b here?
$ echo ',a,,,b,' | ruby -pe 'gsub(/(^|,)\K(?=,|$)/, "NA")'
NA,a,NA,,b,NA

$ # reference from perl, where ^|, is considered as variable length
$ echo ',a,,,b,' | perl -pe 's/(^|,)\K(?=,|$)/NA/g'
NA,a,NA,NA,b,NA
$ echo ',a,,,b,' | perl -pe 's/(?<=^|,)(?=,|$)/NA/g'
Variable length lookbehind not implemented in regex m/(?<=^|,)(?=,|$)/ at -e line 1


注意:我特别希望了解\Kruby中的外观,而不是寻找解决此问题的其他方法,例如:

$ echo ',a,,,b,' | ruby -lne 'print $_.split(",",-1).map { |s| s=="" ? "NA" : s }.join","'
NA,a,NA,NA,b,NA

1 个答案:

答案 0 :(得分:1)

(?<=^|,)(?=,|$)匹配如下:第一个匹配是字符串的开头,因为它跟随,;第二个和第三个逗号之间的第二个匹配;在第二个逗号后检查位置后,检查第三个逗号后的位置,找到第三个匹配;正如预期的那样,最后一个匹配位于字符串的末尾,因为,后跟$(字符串结尾)。

Ruby(Onigmo正则表达式引擎)和PCRE中的(^|,)\K(?=,|$)模式行为有所不同,您可以在regex101.com轻松查看。在PCRE中\K构造匹配第三个逗号后面的空字符串/位置, Onigmo正则表达式引擎无法匹配它,因为正则表达式索引被移动/设置&#34;手动&#34 ;如果匹配为空字符串,则跳过当前测试的字符。这意味着在匹配并消耗第二个,之后,将省略匹配的文本,然后强制正则表达式引擎跳转到第三个逗号后的位置。这意味着(^|,)\K(?=,|$)模式无法在,b之间匹配。