对于给定的正则表达式,R 正则表达式编译器的工作方式不同
Posted
技术标签:
【中文标题】对于给定的正则表达式,R 正则表达式编译器的工作方式不同【英文标题】:R regex compiler working differently for the given regex 【发布时间】:2020-09-13 01:53:47 【问题描述】:我正在完善this的答案;并发现下面给出的正则表达式在R
中无法正常工作(根据其含义)。
+?on.*$
根据我对正则表达式的理解,上面的正则表达式匹配:
懒惰地空格一次或多次,后跟
on
后跟任何内容(换行符除外)直到结束。
输入:
Posted by ondrej on 29 Feb 2020.
Posted by ona'je on 29 Feb 2020.
OUTPUT(根据我的说法,如果测试字符串中的上述正则表达式模式被替换为“”)
Posted by
Posted by
当我尝试在python (implementation here)、javascript 和java (implementation here) 中测试它时;我得到了预期的结果。
const myString = "Posted by ondrej on 29 Feb 2020.\nPosted by ona'je on";
console.log(myString.replace( new RegExp(" +?on.*$","gm"),""));
另一方面,如果我想在R (implementation here) 中实现相同的正则表达式;我得到的结果是
Posted by ondrej
Posted by ona'je
这是出乎意料的。
怀疑
我认为R
的正则表达式解析器的工作方式可能不同(可能从右到左)。我阅读了R
中正则表达式如何工作的文档,但发现上述正则表达式与其他语言没有什么不同。我可能在这里遗漏了一些东西。我不精通R
,但就我的正则表达式知识而言;我相信上述正则表达式应该可以在java
、javascript
和python
(也可能在pcre
中。)适用于每个标准正则表达式引擎(据我所知)。我的问题是为什么上述正则表达式在 R
中的工作方式不同?
【问题讨论】:
我认为您需要在 R 中设置perl = TRUE
以获得作为选项传递给 regex
的相同结果。见?regex
。
谢谢@edsandorf。我可以编写其他正则表达式来获得答案。但是,我很想知道为什么R
会出现这种行为?我对上述正则表达式的理解是错误的还是编译器是从右到左工作的?
【参考方案1】:
它看起来像TRE regex engine(在基本 R 正则表达式函数中默认使用),基于最初由 Henry Spencer 在 1986 年编写的正则表达式库,如果正则中的第一个模式匹配字符串末尾的最短匹配表达式以惰性量词开头,以 $
锚结尾。
比较these cases:
sub(" +?on.*$", "", Data) # "Posted by ondrej" "Posted by ona'je"
sub(" +?on.*", "", Data) # "Posted bydrej on 29 Feb 2020." "Posted bya'je on 29feb 2020"
sub(" +?on(.*)", "", Data) # as expected
sub(" +on.*", "", Data) # as expected
发生了什么事?
第一种情况是sub(" +?on.*$", "", Data)
,第一种模式将所有量词的贪婪设置在正则表达式的同一级别。因此,第二个量词*
,即使没有?
,将设置为惰性,因为第一个空间是用惰性量词+?
量化的。这是一个已知的 TRE“错误”,也存在于其他一些基于 Henry Spencer 的 regexl 库的 regex 引擎中。
第二个 sub(" +?on.*", "", Data)
匹配方式与编写 " +?on.*?"
相同(同样,由于第一个模式将贪婪级别设置为在该级别上延迟)并且 would only match 1 个或多个空格然后on
、.*?
在模式结束时不匹配任何内容。
第三个,sub(" +?on(.*)", "", Data)
,产生了预期的结果,因为第二个量化模式,.*
,在另一个层次上(一个层次深),它的贪婪不受 +?
的影响。是在另一个层面上。所以,(.*)
在这里贪婪匹配。
第四个,sub(" +on.*", "", Data)
,产生了预期的结果,因为第一个模式是贪婪的,所以下一个量化的模式贪婪也是贪婪的。
【讨论】:
感谢您的回答!为什么只返回sub(" +on.*?$", "", Data)
"Posted by"
?
@GKi 第一个模式是贪婪的,并且对于同一级别的所有量词将贪婪设置为贪婪。这已经取消了第一个场景,第一个模式应该以一个惰性量化模式开始,以匹配正确的关联方式。
感谢@WiktorStribiżew 的启发。我还有一个疑问,如果在 TRE 兼容引擎中,每次惰性匹配首先出现时,它会将其他量词变为惰性仅在同一级别?
@Mandy8055 是的,仅在同一级别。像这样的引擎不多,我只知道PostgreSQL、Tcl和TRE。
@WiktorStribiżew 您能否引用提到 R 使用 TRE
的地方。我没有找到这个。我正在阅读文档。我发现只有 POSIX 1003.2 standard 作为默认实现。以上是关于对于给定的正则表达式,R 正则表达式编译器的工作方式不同的主要内容,如果未能解决你的问题,请参考以下文章