2016-05-24 4 views
2

Я пытаюсь найти одно белое пространство, окруженное цифрой с каждой стороны в строке. Я построил следующий пример:Почему это регулярное выражение пропускает одно пробел между двумя цифрами?

library('stringr') 
str1 <- "1805.6 1-1 1" 
str_locate_all(str1, "\\s+")[[1]] 
str_locate_all(str1, "[[:digit:]]\\s[[:digit:]]")[[1]] 

который возвращает:

str_locate_all(str1, "\\s+")[[1]] 
    start end 
[1,]  7 7 
[2,] 11 11 

str_locate_all(str1, "[[:digit:]]\\s[[:digit:]]")[[1]] 
    start end 
[1,]  6 8 
[2,] 10 12 

Что я и ожидал увидеть. Теперь сделайте то же самое с другой строкой:

str2 <- "1805.6 1 1 1" 
str_locate_all(str2, "\\s+")[[1]] 
str_locate_all(str2, "[[:digit:]]\\s[[:digit:]]")[[1]] 

Но это, кажется, пропустить один из пространств, окруженных цифр (обратите внимание, что вторая модель возвращает только 2 записи):

str_locate_all(str2, "\\s+")[[1]] 
    start end 
[1,]  7 7 
[2,]  9 9 
[3,] 11 11 

str_locate_all(str2, "[[:digit:]]\\s[[:digit:]]")[[1]] 
    start end 
[1,]  6 8 
[2,] 10 12 

Так вопрос в том, почему 2-й шаблон не видит среднее белое пространство и возвращает строку с 8 10? Я уверен, что я просто не вижу вещей с мышления regex.

+3

Спички расходуются. Попробуйте найти перекрывающееся регулярное выражение http://stackoverflow.com/search?q=%5Br%5D+overlapping+regex –

+0

Я нахожу этот вывод интересным, хотя 'str_locate_all (str2," (? = (\\ d \\ s \ \ d)) ") [[1]]' Конец перед началом :) –

ответ

3

Ваша цифра после пробега потребляется после матча. Таким образом, вы не можете найти матч. В вашем примере

Примечания: - x обозначает совпадающих цифры

1805.6 1 1 1 
    x^x 
     | 
    First match 

1805.6 1 1 1 
     ^
     | 
Once the regex engine moves forward, it cannot see backward(unless lookbehind is used). 
Here, first digit from regex is matched with space which is not correct so the match fails outright and next position is attempted. 

1805.6 1 1 1  
     x^x 
     ||Matches digit 
     |Matches space 
     Matches digit 
    (Second match) 

This goes on till end of string is reached 

Визуализируйте здесь

enter image description here

Вы можете использовать lookahead вместо этого как

> str_locate_all(str1, "\\d\\s(?=\\d)")[[1]] 
    start end 
[1,]  6 7 
[2,]  8 9 
[3,] 10 11 

Как lookahaeads имеют нулевой width, we g et позиция меньше, чем фактическая конечная позиция.

+0

Спасибо за это ясное объяснение. Связанный вопрос: Существует ли функциональная разница между использованием '[[: digit:]]' vs. '\\ d'? Благодарю. –

+0

@BryanHanson нет, я так не думаю (до тех пор, пока не знаю). Одна вещь, которую я наблюдал, это '[[: digit:]]' поддерживается главным образом механизмом DFA – rock321987

+0

Спасибо. Это было на чит-листах, и я использовал его. В будущем я пойду с более короткой формой. –

Смежные вопросы