2011-09-16 16 views
9

Dada esta cadena:expresiones regulares - volver todos antes de la segunda aparición

DNS000001320_309.0/121.0_t0 

¿Cómo puedo devolver todo antes de la segunda aparición de "_"?

DNS000001320_309.0/121.0 

estoy usando R.

Gracias.

+0

ninguna garantía de que las cuerdas siempre tendrán un segundo _ ? ¿Cómo desea manejar casos donde hay 0 o 1 caracteres de subrayado? – Brian

+0

Siempre tendrá 2 "_" s ... ¡garantizado! La cadena es un 'pegar' de 3 cadenas usando' sep = "_" '. – James

Respuesta

9

Creo que esto podría hacer la tarea (expresiones regulares para que coincida con todo lo que se acaben la última ocurrencia de _):

_([^_]*)$ 

Ej:

> sub('_([^_]*)$', '', "DNS000001320_309.0/121.0_t0") 
[1] "DNS000001320_309.0/121.0" 
+0

Sí, si se camina la expresión regular, 'sub' sería más apropiado que' gsub'. –

+2

Si hay más de dos guiones bajos, esto seleccionará más allá del segundo guión bajo, aunque aparentemente eso no le importa al PO, así que lo señalo solo para la posteridad. – joran

+0

Sí, buen punto @joran. Puede importar al OP, pero puede que no lo sepa. –

11

Personalmente, odio expresiones regulares, así que afortunadamente hay una manera de hacer esto sin ellos, simplemente mediante la división de la cadena:

> s <- "DNS000001320_309.0/121.0_t0"  
> paste(strsplit(s,"_")[[1]][1:2],collapse = "_") 
[1] "DNS000001320_309.0/121.0" 

Aunque, por supuesto, esto supone que siempre habrá al menos 2 de subrayado en su cadena, así que ten cuidado si vectorizas esto y ese no es el caso.

+0

me ganó 12 segundos: p – darckeen

+0

@darckeen Grandes mentes ... como dicen. ;) – joran

+0

+1 para 'strplit' - la forma en que resolvería este problema en R. – daroczig

6

no es bonito, pero esto va a hacer el truco

mystr <- "DNS000001320_309.0/121.0_t0" 

mytok <- paste(strsplit(mystr,"_")[[1]][1:2],collapse="_") 
36

La siguiente secuencia de comandos:

s <- "DNS000001320_309.0/121.0_t0" 
t <- gsub("^([^_]*_[^_]*)_.*$", "\\1", s) 
t 

imprimirá:

DNS000001320_309.0/121.0 

Una explicación rápida de la expresión regular:

^   # the start of the input 
(  # start group 1 
    [^_]* # zero or more chars other than `_` 
    _  # a literal `_` 
    [^_]* # zero or more chars other than `_` 
)   # end group 1 
_   # a literal `_` 
.*  # consume the rest of the string 
$   # the end of the input 

que se sustituye por:

\\1  # whatever is matched in group 1 

Y si hay menos de 2 guiones bajos, la cadena no se cambia.

+0

Guau, realmente agradable, respuesta detallada (+1). Definitivamente me gusta tu solución mejor que la mía :) – daroczig

Cuestiones relacionadas