【问题标题】:Use of \K and lookahead not working as expected使用 \K 和前瞻未按预期工作
【发布时间】:2018-06-30 18:00:25
【问题描述】:

我没有在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

【问题讨论】:

    标签: ruby regex regex-lookarounds


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢,如果我理解正确的话,Onigmo 正则表达式引擎将为/,\K(?=,)/ 和/(?&lt;=,)(?=,)/ 给出不同的结果...您的意见是什么-/,\K(?=,)/ 和/(?&lt;=,)(?=,)/ 应该相同还是不同?还是留给特定的正则表达式引擎实现?
    • @Sundeep 如果你问我,PCRE 实现是正确的,但在不同的场景中都有各自的优缺点,而且我也认为 PCRE 实现的成本更高一些(虽然更“正确” )。
    • 再次感谢..您是否有任何官方链接解释这是预期的行为?如果不是,我可能会在 ruby​​ 网站上打开一个问题并问...我觉得这是一个错误..我尝试了更多,甚至简单的案例将是 gsub(/xyz/, "\\0NA") 而不是 gsub(/xyz\K/, "NA").. perl 和 vim(\ zs) 行为相同.. 刚刚检查过,python 正则表达式模块 \K 与 ruby​​ 相同
    • @Sundeep 我不会称其为错误,它更像是“未定义的行为”。仅当您将非重叠匹配项与非空字符串作为返回值时才使用\K,否则,当您需要获取空匹配项时,请使用环视。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    相关资源
    最近更新 更多