2010-06-03 25 views
44

Tengo lo que es probablemente una pregunta realmente tonta grep en R. Disculpas, porque parece que debería ser tan fácil. Obviamente me falta algo.R: cómo obtener grep para devolver la coincidencia, en lugar de toda la cadena

Tengo un vector de cadenas, llamémoslo alice. Algunos de alice se imprime a continuación:

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 

me gustaría grep que me diera el número después de la D que aparece en algunas de estas cadenas, condicionada a la cadena que contiene "LIS" y una cadena vacía o algo de otra manera.

Tenía la esperanza de que grep me devolviera el valor de un grupo de captura en lugar de toda la cadena. Aquí está mi expresión regular con sabor a R:

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

nada demasiado complicado. Sin embargo, con el fin de conseguir lo que busco, en vez de utilizar grep(pattern, alice, value = TRUE, perl = TRUE) que estoy haciendo lo siguiente, que parece malo:

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

Mirándolo ahora no parece demasiado feo, pero la cantidad de meterse en la trampa para hacer funcionar esta cosa tan trivial ha sido embarazoso. ¿Alguien tiene alguna sugerencia sobre cómo hacer esto correctamente?

Marcas adicionales para señalarme a una página web que explica la diferencia entre lo que acceda con $, @ y attr.

+4

parece que esto ya se ha preguntado y respondido. Disculpas por la repetición! http://stackoverflow.com/questions/2192316/extract-a-regular-expression-match-in-r-version-2-10/2192732#2192732 –

Respuesta

35

Usted puede hacer algo como esto:

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

Si sólo desea que el subconjunto de alice donde su patrón coincide, intente esto:

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

http://xkcd.com/208/ – Marek

+0

impresionante. Muchas gracias. No había pensado en reemplazar la línea con el partido, sino que estaba pensando obsesivamente "¿por qué no me devolverá el partido arggghhh!". Probablemente debería dejar de usar esas cosas de mirar hacia adelante y mirar hacia atrás también ¿eh? Mi cerebro aún no funciona con la expresión regular. Me parece pensar hacia atrás. –

+0

Acabo de encontrar la característica de expresiones regulares que usó Ken Williams anteriormente. Es asombroso. Creo que se llama etiquetado. Se puede escribir una expresión regular y una o más partes de la misma se pueden colocar en paréntesis/paréntesis no protegidos. La función sub o gsub le permite a uno usar \\ 1 o \\ 2 para pegar la coincidencia que estaba en el primer par de corchetes sin capa o el segundo par de corchetes sin capa, respectivamente. Obtenga más información aquí http://books.google.com/books?id=grfuq1twFe4C&lpg=PP1&pg=PA99#v=onepage&q=unescaped&f=false – Farrel

46

Pruebe el paquete stringr:

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

brilliant. ¿No supone que hay planes para que stringr use perl regexps? ¿O es generalmente el caso que uno siempre debe usar el dialecto de R? –

+0

@Mike puede usar expresiones regulares de perl en 'stringr' envolviendo la cadena de expresiones regulares en' perl() '. Ver '? Perl'. –

+0

@SamFirke no más – hadley

Cuestiones relacionadas