R regexp中[0-9] n次和[0-9] {n}之间的差异

时间:2015-02-25 21:53:26

标签: regex r

我认为两者都是相同的,但实际上我看到了不同之处,请看this question中的这个最小例子:

a<-c("/Cajon_Criolla_20141024","/Linon_20141115_20141130",
"/Cat/LIQUID",
"/c_puertas_20141206_20141107",
"/C_Puertas_3_20141017_20141018",
"/c_puertas_navidad_20141204_20141205")

sub("(.*?)_([0-9]{8})(.*)$","\\2",a)
[1] "20141024"    "20141130"    "/Cat/LIQUID" "20141107" "20141018"   
[6] "20141205"   

sub("(.*?)_([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])(.*)$","\\2",a)
[1] "20141024"    "20141115"    "/Cat/LIQUID" "20141206" "20141017"   
[6] "20141204" 

我错过了什么?或者这是一个错误吗?

3 个答案:

答案 0 :(得分:12)

这是TRE库中与贪婪修饰符和捕获组相关的错误。参见:

答案 1 :(得分:4)

设置perl=TRUE为两个表达式提供相同的答案(如预期):

> sub("(.*?)_([0-9]{8})(.*)$","\\2",a,perl=TRUE)
[1] "20141024"    "20141115"    "/Cat/LIQUID" "20141206"    "20141017"    "20141204"   
> sub("(.*?)_([0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])(.*)$","\\2",a,perl=TRUE)
[1] "20141024"    "20141115"    "/Cat/LIQUID" "20141206"    "20141017"    "20141204"

答案 2 :(得分:1)

虽然我最初被BrodieG回答说服,但似乎[0-9] n次和[0-9] {n}确实不同,至少对于“tre”正则表达式电机而言。根据{{​​3}},{}运算符是贪心的,[0-9]不是。

因此,在我的案例中,正确的正则表达应该是:

    sub("(.*?)_([0-9]{8}?)(.*)$","\\2",a)

发挥重要作用:

    sub("(.*?)_([0-9]{8})(.*)$","\\2",a)
    [1] "20141024"    "20141130"    "/Cat/LIQUID" "20141107"    "20141018"   
    [6] "20141205"   
    sub("(.*?)_([0-9]{8}?)(.*)$","\\2",a)
    [1] "20141024"    "20141115"    "/Cat/LIQUID" "20141206"    "20141017"   
    [6] "20141204"

甚至

    > sub("(.*)_([0-9]{8}?)(.*)$","\\2",a)
    [1] "20141024"    "20141115"    "/Cat/LIQUID" "20141206"    "20141017"   
    [6] "20141204"

解释:1)tre考虑?作为“第一次匹配这个原子时评估下一个原子”。 “。?”总是如此。当一切都匹配时,它会切换到_ [0-9] {8}。当到达第一组6个数字时,如果{}不贪婪(不是?),因为(。)也匹配前8个数字,搜索继续查看是否出现另一个“_ [0- 9] {8}“可以在线上找到。如果满足第二组8个数字,它也会将其记忆为匹配模式,然后它到达行尾,保留最后一个匹配模式,[0-9] {8}与第二个8匹配号。

2)当{}运算符被修改时?搜索在第一次看到8个数字时停止,检查_(。*)是否可以与其余数字匹配。它可以,所以它返回第一组8个数字。

请注意, perl regexp电机的工作方式不同,

1)?在{}没有改变之后:

     sub("(.*)_([0-9]{8})","\\2",a,perl=TRUE)
     [1] "20141024"    "20141130"    "/Cat/LIQUID" "20141107"    "20141018"   
     [6] "20141205"   
     sub("(.*)_([0-9]{8}?)","\\2",a,perl=TRUE)
     [1] "20141024"    "20141130"    "/Cat/LIQUID" "20141107"    "20141018"   
     [6] "20141205"
2)?适用于。*使其停止在第一组8个数字:

     sub("(.*?)_([0-9]{8}).*","\\2",a,perl=TRUE)
     [1] "20141024"    "20141115"    "/Cat/LIQUID" "20141206"    "20141017"   
     [6] "20141204"   
     sub("(.*)_([0-9]{8}).*","\\2",a,perl=TRUE)
     [1] "20141024"    "20141130"    "/Cat/LIQUID" "20141107"    "20141018"   
     [6] "20141205" 

从这两个观察结果来看,似乎两个引擎在两个不同的实例中对贪婪的解释不同。我总觉得贪婪概念有点模糊......