2009-11-30 29 views
17

¿Hay algún equivalente a str.split en Python que también devuelve los delimitadores?tokenize una cadena manteniendo delimitadores en Python

Necesito conservar el diseño de espacio en blanco para mi salida después de procesar algunos de los tokens.

Ejemplo:

>>> s="\tthis is an example" 
>>> print s.split() 
['this', 'is', 'an', 'example'] 

>>> print what_I_want(s) 
['\t', 'this', ' ', 'is', ' ', 'an', ' ', 'example'] 

Gracias!

+1

+1 - Interesante pregunta, 'splitlines' parece tener un parámetro' keepends', pero no hay tal cosa para 'split'. Parece extraño (http://docs.python.org/library/stdtypes.html#str.splitlines). –

Respuesta

19

¿Qué tal

import re 
splitter = re.compile(r'(\s+|\S+)') 
splitter.findall(s) 
+0

elegante y fácilmente ampliable (pensar '(\ s + | \ w + | \ S +)'). – hop

6
>>> re.compile(r'(\s+)').split("\tthis is an example") 
['', '\t', 'this', ' ', 'is', ' ', 'an', ' ', 'example'] 
4

el módulo re proporciona esta funcionalidad:

>>> import re 
>>> re.split('(\W+)', 'Words, words, words.') 
['Words', ', ', 'words', ', ', 'words', '.', ''] 

(citado de la documentación de Python).

Para su ejemplo (dividir en espacios en blanco), use re.split('(\s+)', '\tThis is an example').

La clave es encerrar la expresión regular en la que dividir al capturar paréntesis. De esta forma, los delimitadores se agregan a la lista de resultados.

Editar: Como se señaló, cualquier delimitador anterior/posterior, por supuesto, también se agregará a la lista. Para evitar eso, primero puede usar el método .strip() en su cadena de entrada.

+0

sin usar las máscaras de cadena del OP, el hecho de que la cadena vacía se incluye como el primer elemento de la lista devuelta. – hop

+0

Gracias. Edité mi publicación en consecuencia (aunque en este caso, la especificación del OP ("quiero preservar el espacio en blanco") y su ejemplo eran contradictorios). –

+0

No, no fue ... había un ejemplo del comportamiento actual y otro del deseado. – fortran

-1

Gracias chicos por señalar para el módulo re, todavía estoy tratando de decidir entre eso y el uso de mi propia función que devuelve una secuencia ...

def split_keep_delimiters(s, delims="\t\n\r "): 
    delim_group = s[0] in delims 
    start = 0 
    for index, char in enumerate(s): 
     if delim_group != (char in delims): 
      delim_group ^= True 
      yield s[start:index] 
      start = index 
    yield s[start:index+1] 

Si tuviera vez que había referencia a xD

+0

no necesita regex o crear sus propias ruedas si tiene python 2.5 en adelante ... vea mi respuesta. – ghostdog74

3

¿Has mirado pyparsing? Ejemplo tomado de the pyparsing wiki:

>>> from pyparsing import Word, alphas 
>>> greet = Word(alphas) + "," + Word(alphas) + "!" 
>>> hello1 = 'Hello, World!' 
>>> hello2 = 'Greetings, Earthlings!' 
>>> for hello in hello1, hello2: 
...  print (u'%s \u2192 %r' % (hello, greet.parseString(hello))).encode('utf-8') 
... 
Hello, World! → (['Hello', ',', 'World', '!'], {}) 
Greetings, Earthlings! → (['Greetings', ',', 'Earthlings', '!'], {}) 
Cuestiones relacionadas