Подтвердить что ты не робот

R: как заставить grep возвращать совпадение, а не всю строку

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

У меня есть вектор строк, назовем его alice. Ниже приведена часть alice:

T.8EFF.SP.OT1.D5.VSVOVA#4   
T.8EFF.SP.OT1.D6.LISOVA#1  
T.8EFF.SP.OT1.D6.LISOVA#2   
T.8EFF.SP.OT1.D6.LISOVA#3  
T.8EFF.SP.OT1.D6.VSVOVA#4    
T.8EFF.SP.OT1.D8.VSVOVA#3  
T.8EFF.SP.OT1.D8.VSVOVA#4   
T.8MEM.SP#1                
T.8MEM.SP#3                      
T.8MEM.SP.OT1.D106.VSVOVA#2 
T.8MEM.SP.OT1.D45.LISOVA#1  
T.8MEM.SP.OT1.D45.LISOVA#3

Я хочу, чтобы grep дал мне номер после D, который появляется в некоторых из этих строк, при условии строки, содержащей "LIS", и пустую строку или что-то в этом роде.

Я надеялся, что grep вернет мне значение группы захвата, а не целую строку. Здесь мое R-ароматизированное регулярное выражение:

pattern <- (?<=\\.D)([0-9]+)(?=.LIS)

ничего сложного. Но чтобы получить то, что мне нужно, вместо того, чтобы просто использовать grep(pattern, alice, value = TRUE, perl = TRUE), я делаю следующее, что кажется плохим:

reg.out <- regexpr(
    "(?<=\\.D)[0-9]+(?=.LIS)",
    alice,
    perl=TRUE
)
substr(alice,reg.out,reg.out + attr(reg.out,"match.length")-1)

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

Бонусные знаки для указания на веб-страницу, которая объясняет разницу между тем, что я получаю с помощью $, @ и attr.

4b9b3361

Ответ 1

Вы можете сделать что-то вроде этого:

pat <- ".*\\.D([0-9]+)\\.LIS.*"
sub(pat, "\\1", alice)

Если вы хотите только подмножество alice, где находится ваш шаблон, попробуйте следующее:

pat <- ".*\\.D([0-9]+)\\.LIS.*"
sub(pat, "\\1", alice[grepl(pat, alice)])

Ответ 2

Попробуйте пакет stringr:

library(stringr)
str_match(alice, ".*\\.D([0-9]+)\\.LIS.*")[, 2]