Pregunta

Necesito poder tomar una cadena como:

'''foo, bar, "one, two", three four'''

en:

['foo', 'bar', 'one, two', 'three four']

Tengo la sensación (con sugerencias de #python) de que la solución involucrará el módulo shlex.

¿Fue útil?

Solución

La solución del módulo shlex permite comillas escapadas, una cita escapa a otra y todo lo sofisticado que admite el shell.

>>> import shlex
>>> my_splitter = shlex.shlex('''foo, bar, "one, two", three four''', posix=True)
>>> my_splitter.whitespace += ','
>>> my_splitter.whitespace_split = True
>>> print list(my_splitter)
['foo', 'bar', 'one, two', 'three', 'four']

Ejemplo de comillas escapadas:

>>> my_splitter = shlex.shlex('''"test, a",'foo,bar",baz',bar \xc3\xa4 baz''',
                              posix=True) 
>>> my_splitter.whitespace = ',' ; my_splitter.whitespace_split = True 
>>> print list(my_splitter)
['test, a', 'foo,bar",baz', 'bar \xc3\xa4 baz']

Otros consejos

Depende de lo complicado que quieras ponerte...¿Quieres permitir más de un tipo de cotización?¿Qué tal las comillas escapadas?

Su sintaxis se parece mucho al formato de archivo CSV común, que es compatible con la biblioteca estándar de Python:

import csv
reader = csv.reader(['''foo, bar, "one, two", three four'''], skipinitialspace=True)
for r in reader:
  print r

Salidas:

['foo', 'bar', 'one, two', 'three four']

¡HH!

Quizás también quieras considerar el csv módulo.No lo he probado, pero parece que sus datos de entrada están más cerca de CSV que de la sintaxis de Shell (que es lo que analiza shlex).

Podrías hacer algo como esto:

>>> import re
>>> pattern = re.compile(r'\s*("[^"]*"|.*?)\s*,')
>>> def split(line):
...  return [x[1:-1] if x[:1] == x[-1:] == '"' else x
...          for x in pattern.findall(line.rstrip(',') + ',')]
... 
>>> split("foo, bar, baz")
['foo', 'bar', 'baz']
>>> split('foo, bar, baz, "blub blah"')
['foo', 'bar', 'baz', 'blub blah']

Yo diría que lo que estás buscando aquí sería una expresión regular, aunque no estoy muy familiarizado con el motor Regex de Python.

Suponiendo que utiliza coincidencias diferidas, puede obtener un conjunto de coincidencias en una cadena que puede colocar en su matriz.

Si no es necesario que sea bonito, esto podría ayudarte:

def f(s, splitifeven):
    if splitifeven & 1:
        return [s]
    return [x.strip() for x in s.split(",") if x.strip() != '']

ss = 'foo, bar, "one, two", three four'

print sum([f(s, sie) for sie, s in enumerate(ss.split('"'))], [])
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top