Разница между [0-9] n раз и [0-9] {n} в R regexp

Оба, насколько мне известно, должны быть такими же, но я действительно вижу разницу, посмотрите на этот минимальный пример из этого вопроса:

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" 

Что мне не хватает? Или это ошибка?

Ответы

Ответ 2

Настройка 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"

Ответ 3

Хотя я был сначала убежден в ответ BrodieG, кажется, что [0-9] n раз и [0-9] {n} действительно отличаются друг от друга, по крайней мере, для двигателя "tre" regexp. Согласно http://www.regular-expressions.info оператор {} жадный, [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 чисел.

Обратите внимание, что двигатель regexp perl работает по-разному,

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" 

Из этих двух наблюдений кажется, что эти два двигателя по-разному трактуют жадность в двух разных случаях. Я всегда считал, что концепция жадности немного расплывчата...