Ответ 1
Это ошибка в библиотеке TRE, относящаяся к жадным модификаторам и группам захвата. См:
- Вопрос с аналогичной проблемой
- Проблема №11 на TRE repo
- Проблема № 21.
Оба, насколько мне известно, должны быть такими же, но я действительно вижу разницу, посмотрите на этот минимальный пример из этого вопроса:
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"
Что мне не хватает? Или это ошибка?
Это ошибка в библиотеке TRE, относящаяся к жадным модификаторам и группам захвата. См:
Настройка 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"
Хотя я был сначала убежден в ответ 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"
Из этих двух наблюдений кажется, что эти два двигателя по-разному трактуют жадность в двух разных случаях. Я всегда считал, что концепция жадности немного расплывчата...