2013-05-23 14 views
11

con Python, voglio dividere la seguente stringa:Python: dividere una stringa, rispettare e preservare le citazioni

a=foo, b=bar, c="foo, bar", d=false, e="false" 

Ciò dovrebbe tradursi nel seguente elenco:

['a=foo', 'b=bar', 'c="foo, bar"', 'd=false', 'e="false'"'] 

Quando si utilizza shlex in posix-mode e splitting con ",", l'argomento per c viene trattato correttamente. Tuttavia, rimuove le virgolette. Ho bisogno di loro perché false non è lo stesso di "false", per esempio.

Il mio codice finora:

import shlex 

mystring = 'a=foo, b=bar, c="foo, bar", d=false, e="false"' 

splitter = shlex.shlex(mystring, posix=True) 
splitter.whitespace += ',' 
splitter.whitespace_split = True 
print list(splitter) # ['a=foo', 'b=bar', 'c=foo, bar', 'd=false', 'e=false'] 
+2

Possono esserci virgolette (sfuggite) tra virgolette? –

+0

Sì, possono (fuggire con una barra rovesciata). – Remo

+0

Credo che questo sia un duplicato di http://stackoverflow.com/a/79985/1540600, che fornisce una risposta superiore. (Usa 'shlex.split()'.) – sferencik

risposta

19
>>> s = r'a=foo, b=bar, c="foo, bar", d=false, e="false", f="foo\", bar"' 
>>> re.findall(r'(?:[^\s,"]|"(?:\\.|[^"])*")+', s) 
['a=foo', 'b=bar', 'c="foo, bar"', 'd=false', 'e="false"', 'f="foo\\", bar"'] 
  1. Il modello di espressione regolare "[^"]*" corrisponde a una semplice stringa tra virgolette.
  2. "(?:\\.|[^"])*" corrisponde a una stringa tra virgolette e salta le virgolette con escape perché \\. consuma due caratteri: una barra rovesciata e qualsiasi carattere.
  3. [^\s,"] corrisponde a un non-delimitatore.
  4. La combinazione di modelli 2 e 3 all'interno di (?: |)+ corrisponde a una sequenza di non-delimitatori e stringhe tra virgolette, che è il risultato desiderato.
+0

Grazie, funziona come un fascino! – Remo

+2

spiega come funziona e invierò un voto in più –

+1

@JasonS Sono d'accordo, ma [regex101.com] (https://regex101.com/) ha una sezione di spiegazione utile che può aiutare, ad esempio: https: //i.imgur .com/SJMAQPI.png – blah238

0

Regex può risolvere questo abbastanza facilmente:

import re 

mystring = 'a=foo, b=bar, c="foo, bar", d=false, e="false"' 

splitString = re.split(',?\s(?=\w+=)',mystring) 

Il modello regex qui sembra per uno spazio bianco seguito da un carattere di parola e quindi un segno di uguale che divide la stringa come si desidera e mantiene tutte le citazioni.

+1

Questo dividerebbe ''c =" foo, bar = "'' –

+0

Punto giusto. Immagino che questo sia il problema con regex, scrivere qualcosa di meno esplicito sembra sempre catturarti con casi inaspettati, eppure la regex esplicita può sembrare orribile da leggere e capire cosa sta succedendo. – ydaetskcoR

Problemi correlati