2012-03-16 20 views
6

La manera más fácil de explicar esto es un ejemplo: tengo esta cadena: 'Docs/src/Scripts/temp' que sé cómo dividir dos maneras diferentes:Python Regex de Split Mantiene Dividir Patrón Caracteres

re.split('/', 'Docs/src/Scripts/temp') -> ['Docs', 'src', 'Scripts', 'temp'] 

re.split('(/)', 'Docs/src/Scripts/temp') -> ['Docs', '/', 'src', '/', 'Scripts', '/', 'temp'] 

¿Hay alguna manera de dividir por la barra diagonal, pero mantener la barra oblicua de las palabras? Por ejemplo, quiero que la cadena anterior a este aspecto:

['Docs/', '/src/', '/Scripts/', '/temp'] 

Cualquier ayuda se agradece!

+0

Se es 're.split ('(/)', ...)', 'no re.split (('/'), ...) '. –

Respuesta

8

Interesante pregunta, yo sugeriría hacer algo como esto:

>>> 'Docs/src/Scripts/temp'.replace('/', '/\x00/').split('\x00') 
['Docs/', '/src/', '/Scripts/', '/temp'] 

La idea aquí es reemplazar primero todos / caracteres por dos / caracteres separados por un carácter especial que no sería una parte del original cuerda. Utilicé un byte nulo ('\x00'), pero podría cambiar esto a otra cosa, y finalmente dividir ese carácter especial.

Regex no es muy bueno aquí porque no se puede dividir en coincidencias de longitud cero, y re.findall() no encuentra coincidencias superpuestas, por lo que es posible que tenga que hacer varias pasadas sobre la cadena.

Además, re.split('/', s) hará lo mismo que s.split('/'), pero el segundo es más eficiente.

+0

¡Gracias por la respuesta! – user1274774

+1

Hacer la división y unir es como ''Documentos/src/Scripts/temp'.replace ('/', '/ \ x00 /')' –

+0

@gnibbler - ¡Qué tonto, gracias que es mucho más limpio! Edité mi respuesta para usar eso en su lugar. –

1

No estoy seguro de que haya una manera fácil de hacerlo. Esto es lo mejor que podía llegar a ...

import re 

lSplit = re.split('/', 'Docs/src/Scripts/temp') 
print [lSplit[0]+'/'] + ['/'+x+'/' for x in lSplit][1:-1] + ['/'+lSplit[len(lSplit)-1]] 

especie de desastre, pero que sí hace lo que quería.

+0

¿Por qué necesita expresiones regulares cuando se divide en un solo carácter de todos modos? – hop

+0

No es así. Puede usar un str.split() si lo desea. La respuesta de F.J es mejor que la mía de todos modos. – b10hazard

3

1) No es necesario expresiones regulares para dividir en un solo carácter fijo:

>>> 'Docs/src/Scripts/temp'.split('/') 

[ 'Docs', 'src', 'Scripts', 'temp']

2) considere el uso de este método:

import os.path 

def components(path): 
    start = 0 
    for end, c in enumerate(path): 
     if c == os.path.sep: 
      yield path[start:end+1] 
      start = end 
    yield path[start:] 

no se basa en trucos inteligentes como Split-join-división, lo que hace que sea mucho más fácil de leer, en mi opinión.

2

Si no insiste en tener rayas verticales en ambos lados, de hecho es bastante simple:

>>> re.findall(r"([^/]*/)", 'Docs/src/Scripts/temp') 
['Docs/', 'src/', 'Scripts/'] 

Ni re ni Split están realmente hecha para cuerdas superpuestas, así que si eso es lo que realmente quiere, yo Simplemente agregue una barra al comienzo de cada resultado, excepto el primero.

5

Una solución sin split() pero con los símbolos de anticipación:

>>> s = 'Docs/src/Scripts/temp' 
>>> r = re.compile(r"(?=((?:^|/)[^/]*/?))") 
>>> r.findall(s) 
['Docs/', '/src/', '/Scripts/', '/temp'] 

Explicación:

(?=  # Assert that it's possible to match... 
(  # and capture... 
    (?:^|/) # the start of the string or a slash 
    [^/]* # any number of non-slash characters 
    /?  # and (optionally) an ending slash. 
)   # End of capturing group 
)   # End of lookahead 

Dado que una afirmación de búsqueda hacia delante se trató en cada posición en la cadena y no consume ningún carácter, no tiene ningún problema con la coincidencia de coincidencias.

+0

¡Ah, he trabajado esta pregunta solo por diversión y he salido con la misma expresión regular que tú, personaje por personaje! (Excepto que tenía un '+' donde tenías un '*') :) +1 – zx81

2

Trata acerca de esto:

re.split(r'(/)', 'Docs/src/Scripts/temp') 

De la documentación del pitón

re.split (patrón, cuerda, maxsplit = 0, banderas = 0)

Separar una cadena por el ocurrencias del patrón. Si se usan paréntesis de captura en el patrón, , entonces el texto de todos los grupos en el patrón también se devuelve como parte de la lista resultante. Si maxsplit es distinto de cero, como máximo se dividen las divisiones max , y el resto de la cadena se devuelve como el elemento final de la lista. (Incompatibilidad nota:. En la versión original de Python 1.5 , fue ignorada maxsplit Esto se ha corregido en versiones posteriores.)

+0

Lo siento, pero confunde. –