2013-05-23 14 views
11

Pythonie, chcę podzielić następujący ciąg:Python: podzielić ciąg, szacunku i zachowania cytaty

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

ten powinien wynikać w poniższej listy:

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

Podczas korzystania shlex w posix-mode i dzielenie na "," argument dla c zostaje potraktowany poprawnie. Jednak usuwa cytaty. Potrzebuję ich, ponieważ false to nie to samo co "false".

Mój kod do tej pory:

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

Czy w cudzysłowie mogą być cytowane cytaty? –

+0

Tak, mogą (uciekają z odwrotnym ukośnikiem). – Remo

+0

Wierzę, że jest to duplikat http://stackoverflow.com/a/79985/1540600, który zapewnia lepszą odpowiedź. (Użyj 'shlex.split()'.) – sferencik

Odpowiedz

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. Wzór regex "[^"]*" pasuje prosty cudzysłowie.
  2. "(?:\\.|[^"])*" dopasowuje cytowany ciąg znaków i przeskakuje nad wyciętymi cudzysłowami, ponieważ \\. zawiera dwa znaki: odwrócony ukośnik i dowolną postać.
  3. [^\s,"] pasuje do ogranicznika.
  4. Łączenie wzorów 2 i 3 w kodzie (?: |)+ dopasowuje ciąg znaków bez ograniczników i ciągów cytowanych, co jest pożądanym wynikiem.
+0

Dziękuję, działa jak urok! – Remo

+2

wyjaśnij, jak to działa, a ja przegłosuję: –

+1

@JasonS Zgadzam się, ale [regex101.com] (https://regex101.com/) zawiera przydatną sekcję wyjaśniającą, która może pomóc, np .: https: //i.imgur .com/SJMAQPI.png – blah238

0

Regex może rozwiązać ten problem dość łatwo:

import re 

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

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

Wzór regex tutaj szuka spacji następnie znakiem słowa, a następnie znak równości, która dzieli swój ciąg, jak chcesz i utrzymuje żadnych cytatów.

+1

To podzieliłoby '' c = "foo, bar =" '' –

+0

Punkt równości. Domyślam się, że to jest problem z regex, pisanie czegoś mniej jawnego zawsze wydaje się przykuwać cię z nieoczekiwanymi przypadkami, a jednak wyraźne wyrażenie regularne może wyglądać okropnie, aby przeczytać i zrozumieć, co się dzieje. – ydaetskcoR

Powiązane problemy