Extrae un partido de expresión regular

Estoy tratando de extraer un número de una cadena.

Y haga algo como [0-9]+ en la cadena "aaa12xxx" y obtenga "12" .

Pensé que sería algo así como:

 > grep("[0-9]+", "aaa12xxx", value=TRUE) [1] "aaa12xxx" 

Y luego pensé …

 > sub("[0-9]+", "\\1", "aaa12xxx") [1] "aaaxxx" 

Pero obtuve alguna forma de respuesta:

 > sub("[0-9]+", "ARGH!", "aaa12xxx") [1] "aaaARGH!xxx" 

Hay un pequeño detalle que me estoy perdiendo.

Use el nuevo paquete stringr que envuelve toda la expresión regular existente opera en una syntax consistente y agrega algunas que faltan:

 library(stringr) str_locate("aaa12xxx", "[0-9]+") # start end # [1,] 4 5 str_extract("aaa12xxx", "[0-9]+") # [1] "12" 

Probablemente sea un poco apresurado decir ‘ ignorar las funciones estándar ‘ – el archivo de ayuda para ?gsub incluso hace referencia específica en ‘Ver también’:

‘regmatches’ para extraer subcadenas coincidentes en función de los resultados de ‘regexpr’, ‘gregexpr’ y ‘regexec’.

Entonces esto funcionará, y es bastante simple:

 txt <- "aaa12xxx" regmatches(txt,regexpr("[0-9]+",txt)) #[1] "12" 

Tal vez

 gsub("[^0-9]", "", "aaa12xxxx") # [1] "12" 

Puede usar la concordancia perezosa de PERG regexs:

 > sub(".*?([0-9]+).*", "\\1", "aaa12xx99",perl=TRUE) [1] "12" 

Intentar sustituir números que no sean dígitos dará lugar a un error en este caso.

Utilice la captura de paréntesis en la expresión regular y las referencias de grupo en el reemplazo. Cualquier cosa entre paréntesis es recordado. Luego se accede por \ 2, el primer elemento. La primera barra invertida escapa a la interpretación de la barra invertida en R para que pase al analizador de expresiones regulares.

 gsub('([[:alpha:]]+)([0-9]+)([[:alpha:]]+)', '\\2', "aaa12xxx") 

Una forma sería esta:

 test <- regexpr("[0-9]+","aaa12456xxx") 

Ahora, observe que regexpr le da los índices iniciales y finales de la cadena:

  > test [1] 4 attr(,"match.length") [1] 5 

Entonces puedes usar esa información con la función substr

 substr("aaa12456xxx",test,test+attr(test,"match.length")-1) 

Estoy seguro de que hay una forma más elegante de hacerlo, pero esta fue la forma más rápida que pude encontrar. Alternativamente, puede usar sub / gsub para quitar lo que no desea dejar lo que desea.

Usando strapply en el paquete gsubfn. strapply es como aplicar en que los argumentos son objeto, modificador y función, excepto que el objeto es un vector de cadenas (en lugar de una matriz) y el modificador es una expresión regular (en lugar de un margen):

 library(gsubfn) x <- c("xy13", "ab 12 cd 34 xy") strapply(x, "\\d+", as.numeric) # list(13, c(12, 34)) 

Esto dice que coincida con uno o más dígitos (\ d +) en cada componente de x pasando cada coincidencia por as.numeric. Devuelve una lista cuyos componentes son vectores de coincidencias de los componentes respectivos de x. Al mirar la salida, vemos que el primer componente de x tiene una coincidencia que es 13 y el segundo componente de x tiene dos coincidencias, que son 12 y 34. Consulte http://gsubfn.googlecode.com para obtener más información.

Otra solución:

 temp = regexpr('\\d', "aaa12xxx"); substr("aaa12xxx", temp[1], temp[1]+attr(temp,"match.length")[1]) 

Una diferencia importante entre estos enfoques es el comportamiento con cualquier no coincidencia. Por ejemplo, el método de ajuste no puede devolver una cadena de la misma longitud que la entrada si no hay una coincidencia en todas las posiciones

 > txt <- c("aaa12xxx","xyz") > regmatches(txt,regexpr("[0-9]+",txt)) # could cause problems [1] "12" > gsub("[^0-9]", "", txt) [1] "12" "" > str_extract(txt, "[0-9]+") [1] "12" NA 

Puede escribir sus funciones de expresiones regulares con C ++, comstackrlas en una DLL y llamarlas desde R.

  #include  extern "C" { __declspec(dllexport) void regex_match( const char **first, char **regexStr, int *_bool) { std::cmatch _cmatch; const char *last = *first + strlen(*first); std::regex rx(*regexStr); bool found = false; found = std::regex_match(*first,last,_cmatch, rx); *_bool = found; } __declspec(dllexport) void regex_search_results( const char **str, const char **regexStr, int *N, char **out ) { std::string s(*str); std::regex rgx(*regexStr); std::smatch m; int i=0; while(std::regex_search(s,m,rgx) && i < *N) { strcpy(out[i],m[0].str().c_str()); i++; s = m.suffix().str(); } } }; 

llamar en R como

 dyn.load("C:\\YourPath\\RegTest.dll") regex_match <- function(str,regstr) { .C("regex_match",x=as.character(str),y=as.character(regstr),z=as.logical(1))$z } regex_match("abc","a(b)c") regex_search_results <- function(x,y,n) { .C("regex_search_results",x=as.character(x),y=as.character(y),i=as.integer(n),z=character(n))$z } regex_search_results("aaa12aa34xxx", "[0-9]+", 5)