Tengo una cadena que es así:
this is "a test"
Estoy tratando de escribir algo en Python para dividirlo por espacio e ignorar espacios entre comillas. El resultado que estoy buscando es:
['this','is','a test']
PD. Sé que va a preguntar "qué sucede si hay comillas dentro de las comillas, bueno, en mi solicitud, eso nunca sucederá.
Respuestas:
Usted quiere
split
, desde elshlex
módulo incorporado .Esto debería hacer exactamente lo que quieres.
fuente
shlex.split('this is "a test"', posix=False)
vuelve['this', 'is', '"a test"']
shlex.split()
desencadenará unaUnicodeEncodeError
excepción.Echa un vistazo al
shlex
módulo, en particularshlex.split
.fuente
Veo enfoques de expresiones regulares aquí que parecen complejos y / o incorrectos. Esto me sorprende, porque la sintaxis de expresiones regulares puede describir fácilmente "espacios en blanco o cosas entre comillas", y la mayoría de los motores de expresiones regulares (incluido Python) pueden dividirse en una expresión regular. Entonces, si vas a usar expresiones regulares, ¿por qué no decir exactamente lo que quieres decir ?:
Explicación:
Shlex probablemente proporciona más funciones, sin embargo.
fuente
Dependiendo de su caso de uso, también puede consultar el
csv
módulo:Salida:
fuente
""
) para representar una comilla doble"
, por lo que convertirá dos comillas dobles en una comilla simple'this is "a string""'
y'this is "a string"""'
ambas se asignarán a['this', 'is', 'a string"']
Uso shlex.split para procesar 70,000,000 líneas de registro de calamar, es muy lento. Entonces cambié a re.
Intente esto si tiene problemas de rendimiento con shlex.
fuente
Como esta pregunta está etiquetada con expresiones regulares, decidí probar un enfoque de expresiones regulares. Primero reemplazo todos los espacios en las partes de comillas con \ x00, luego los separo por espacios, luego reemplazo los \ x00 por espacios en cada parte.
Ambas versiones hacen lo mismo, pero Splitter es un poco más legible que Splitter2.
fuente
Parece que por razones de rendimiento
re
es más rápido. Aquí está mi solución usando un operador menos codicioso que conserva las comillas externas:Resultado:
Deja construcciones como
aaa"bla blub"bbb
juntas, ya que estos tokens no están separados por espacios. Si la cadena contiene caracteres escapados, puede coincidir así:Tenga en cuenta que esto también coincide con la cadena vacía
""
por medio de la\S
parte del patrón.fuente
,
Vía'(?:".*?"|[^,])+'
). Lo mismo se aplica a los caracteres entre comillas.El principal problema con el
shlex
enfoque aceptado es que no ignora los caracteres de escape fuera de las subcadenas citadas, y da resultados ligeramente inesperados en algunos casos de esquina.Tengo el siguiente caso de uso, donde necesito una función dividida que divida las cadenas de entrada de modo que se mantengan las subcadenas entre comillas simples o dobles, con la capacidad de escapar de las comillas dentro de dicha subcadena. Las comillas dentro de una cadena sin comillas no deben tratarse de manera diferente a cualquier otro carácter. Algunos ejemplos de casos de prueba con la salida esperada:
Terminé con la siguiente función para dividir una cadena de modo que los resultados de salida esperados para todas las cadenas de entrada:
La siguiente aplicación de prueba verifica los resultados de otros enfoques (
shlex
ycsv
por ahora) y la implementación de división personalizada:Salida:
Por lo tanto, el rendimiento es mucho mejor
shlex
y se puede mejorar aún más mediante la precompilación de la expresión regular, en cuyo caso superará elcsv
enfoque.fuente
shlex
que no se comporta como se esperaba para mis casos de uso.Para preservar las comillas use esta función:
fuente
Prueba de velocidad de diferentes respuestas:
fuente
Hmm, parece que no puedo encontrar el botón "Responder" ... de todos modos, esta respuesta se basa en el enfoque de Kate, pero divide correctamente las cadenas con subcadenas que contienen comillas escapadas y también elimina las comillas de inicio y finalización de las subcadenas:
Esto funciona en cadenas como
'This is " a \\\"test\\\"\\\'s substring"'
(desafortunadamente, el marcado loco es necesario para evitar que Python elimine los escapes).Si no se desean los escapes resultantes en las cadenas de la lista devuelta, puede usar esta versión ligeramente alterada de la función:
fuente
Para evitar los problemas de Unicode en algunas versiones de Python 2, sugiero:
fuente
split = lambda a: [b.decode('utf-8') for b in _split(a)]
contrario, obtendrá:UnicodeDecodeError: 'ascii' codec can't decode byte ... in position ...: ordinal not in range(128)
Como opción, prueba tssplit:
fuente
Yo sugiero:
cadena de prueba:
para capturar también "" y '':
resultado:
para ignorar "" y '' vacíos:
resultado:
fuente
re.findall("(?:\".*?\"|'.*?'|[^\s'\"]+)", s)
también.Si no te importan las subcadenas que un simple
Actuación:
O módulo de cadena
Rendimiento: el módulo de cadena parece funcionar mejor que los métodos de cadena
O puedes usar el motor RE
Actuación
Para cadenas muy largas, no debe cargar toda la cadena en la memoria y, en su lugar, dividir las líneas o usar un bucle iterativo
fuente
Prueba esto:
Algunas cadenas de prueba:
fuente
adamsplit("This is 'a test'")
→['This', 'is', "'a", "test'"]