我很确定我在这里遗漏了一些明显的东西,但是我不能让R使用非贪婪的正则表达式:
> library(stringr)
> str_match('xxx aaaab yyy', "a.*?b")
[,1]
[1,] "aaaab"
Run Code Online (Sandbox Code Playgroud)
基本函数的行为方式相同:
> regexpr('a.*?b', 'xxx aaaab yyy')
[1] 5
attr(,"match.length")
[1] 5
attr(,"useBytes")
[1] TRUE
Run Code Online (Sandbox Code Playgroud)
我希望这场比赛符合http://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html中的ab '贪婪'评论:
默认情况下,重复是贪婪的,因此使用最大可能的重复次数.这可以通过附加改为'minimal'吗?到量词.(还有其他量词允许近似匹配:请参阅TRE文档.)
有人可以解释一下发生了什么事吗?
更新.令人抓狂的是,在其他一些情况下,非贪婪模式的行为符合预期:
> str_match('xxx <a href="abc">link</a> yyy <h1>Header</h1>', '<a.*>')
[,1]
[1,] "<a href=\"abc\">link</a> yyy <h1>Header</h1>"
> str_match('xxx <a href="abc">link</a> yyy <h1>Header</h1>', '<a.*?>')
[,1]
[1,] "<a href=\"abc\">"
Run Code Online (Sandbox Code Playgroud)
flo*_*del 24
困难的概念,所以我会尽我所能...如果有点混乱,有人可以自由编辑和解释更好.
从左到右搜索与您的模式匹配的表达式.是的,所有的下列字符串aaaab,aaab,aab,和ab对你的模式匹配,但aaaab作为启动最给左边的一个是返回的一个.
所以在这里,你的非贪婪模式不是很有用.也许这个其他的例子可以帮助你更好地理解非贪婪的模式:
str_match('xxx aaaab yyy', "a.*?y")
# [,1]
# [1,] "aaaab y"
Run Code Online (Sandbox Code Playgroud)
这里所有的琴弦aaaab y,aaaab yy,aaaab yyy匹配的模式,并在同一位置开始,但第一个是因为非贪婪模式的返回.
那么你能做些什么才能抓住最后一个ab呢?用这个:
str_match('xxx aaaab yyy', ".*(a.*b)")
# [,1] [,2]
# [1,] "xxx aaaab" "ab"
Run Code Online (Sandbox Code Playgroud)
它是如何工作的?通过.*在前面添加贪婪模式,您现在强制进程将最后一个a放入捕获的组中.
该问题是匹配两个字符串之间的最短的窗口.@flodel正确地提到正则表达式引擎正在从左到右解析字符串,因此所有匹配都是最左边的.贪婪和懒惰只适用于右边界:贪婪量词使得子串到达最右边界,而懒惰量子将匹配第一次出现的子图案.
看看例子:
> library(stringr)
> str_extract('xxx aaaab yyy', "a[^ab]*b")
[1] "ab"
> str_extract('xxx aaa xxx aaa zzz', "xxx.*?zzz")
[1] "xxx aaa xxx aaa zzz"
> str_extract('xxx aaa xxx aaa zzz', "xxx(?:(?!xxx|zzz).)*zzz")
[1] "xxx aaa zzz"
Run Code Online (Sandbox Code Playgroud)
第一个和第三个场景返回最短窗口,第二个窗口是当前问题的图示但具有多字符输入.
场景1.边界是单个字符
在壳体a和b是单个字符,最短窗口是通过使用否定的字符类中找到.a[^ab]*b很容易抓住子串a直到下一个b没有as和bs之间.
场景2.边界不是单个字符
在这些可以进一步展开的情况下,您可以使用淬火贪婪令牌.的xxx(?:(?!xxx|zzz).)*zzz模式相匹配xxx,则比断行字符不是一个起始字符以外的任何字符0+ xxx或zzz字符序列((?!xxx|zzz)是负先行失败比赛,如果子立即向右先行图案匹配),然后a zzz.
这些匹配方案可以很容易地与base R一起regmatches使用(使用支持前瞻的PCRE正则表达式):
> x <- 'xxx aaa xxx aaa zzz xxx bbb xxx ccc zzz'
> unlist(regmatches(x, gregexpr("xxx(?:(?!xxx|zzz).)*zzz", x, perl = TRUE)))
[1] "xxx aaa zzz" "xxx ccc zzz"
Run Code Online (Sandbox Code Playgroud)
一注:使用基础R一个PCRE正则表达式,或在ICU正则表达式时str_extract/ str_match时,.不匹配换行符字符,以使这种行为,你需要添加(?s)在模式开始(内嵌DOTALL修饰符).