我在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
注意:我特别希望了解\K
和ruby
中的外观,而不是寻找解决此问题的其他方法,例如:
$ echo ',a,,,b,' | ruby -lne 'print $_.split(",",-1).map { |s| s=="" ? "NA" : s }.join","'
NA,a,NA,NA,b,NA
答案 0 :(得分:1)
(?<=^|,)(?=,|$)
匹配如下:第一个匹配是字符串的开头,因为它跟随,
;第二个和第三个逗号之间的第二个匹配;在第二个逗号后检查位置后,检查第三个逗号后的位置,找到第三个匹配;正如预期的那样,最后一个匹配位于字符串的末尾,因为,
后跟$
(字符串结尾)。
Ruby(Onigmo正则表达式引擎)和PCRE中的(^|,)\K(?=,|$)
模式行为有所不同,您可以在regex101.com轻松查看。在PCRE中\K
构造匹配第三个逗号后面的空字符串/位置, Onigmo正则表达式引擎无法匹配它,因为正则表达式索引被移动/设置&#34;手动&#34 ;如果匹配为空字符串,则跳过当前测试的字符。这意味着在匹配并消耗第二个,
之后,将省略匹配的文本,然后强制正则表达式引擎跳转到第三个逗号后的位置。这意味着(^|,)\K(?=,|$)
模式无法在,
和b
之间匹配。