2011-11-21 22 views
11

Chciałbym podzielić ciąg na przecinkami, ale ignorować przypadków, gdy jest to w cudzysłowie:Podział ciąg, ignorując separator w cudzysłowie (python)

na przykład:

teststring = '48, "one, two", "2011/11/03"' 
teststring.split(",") 
['48', ' "one', ' two"', ' "2011/11/03"'] 

i wyjście, które chciałbym, to:

['48', ' "one, two"', ' "2011/11/03"'] 

Czy to możliwe?

Odpowiedz

1

Należy użyć biblioteki Python csv: http://docs.python.org/library/csv.html

+1

Powiązanie to nie wystarczy, aby rozwiązać ten problem. Już po wyjęciu z pudełka czytnik csv nie przetworzy poprawnie ciągu testowego OP. –

6

Można użyć the csv module ze standardowej biblioteki:

>>> import csv 
>>> testdata = ['48, "one, two", "2011/11/03"'] 
>>> testcsv = csv.reader(testdata,skipinitialspace=True) 
>>> testcsv.next() 
['48', 'one, two', '2011/11/03'] 

Jedyną rzeczą, aby zwrócić uwagę na to, że csv.reader obiekty oczekiwać iterator który będzie zwraca łańcuch za każdym razem, gdy wywoływana jest nazwa next(). Oznacza to, że nie możesz przekazać łańcucha znaków prosto do reader(), ale możesz zamknąć go na liście jak wyżej.

Musisz zachować ostrożność przy formatowaniu swoich danych lub powiedzieć csv jak sobie z tym poradzić. Domyślnie , cytaty muszą nadejść natychmiast po przecinku lub moduł csv zinterpretuje to pole jako rozpoczynające się spacją zamiast cytowania. Możesz to naprawić, używając the skipinitialspace option.

+0

To nie rozwiązuje problemu PO. "jeden, dwa" nie powinny być podzielone, ponieważ przecinek znajduje się w cudzysłowach, czy też źle zinterpretuję coś? Próbowałem tego tutaj samodzielnie i otrzymałem taki sam wynik jak ty, czytając dokument [csv] (http://docs.python.org/library/csv.html#dialects-andformatting-parameters), zrozumiałem to domyślnie powinien nosić wszystko w cudzysłowach jako jedno pole, domyślnie. – stema

+0

@Dostęp webb: Djmac chce "jeden, dwa" 'w pojedynczej zmiennej, której nie ma w twojej odpowiedzi ... on wymaga danych wyjściowych jako' ['48', '"jeden, dwa" "," "2011/11/03 "']', długość = 3 w twoim przypadku długość = 4 – avasal

+0

@stema - Dobry punkt! Nie przeczytałem dokładnie kodu wyjściowego mojego kodu. Okazuje się, że problem dotyczy przykładowych danych.Jeśli pole zaczyna się spacją, to 'csv' przyjmuje, że pole też działa, a' '' jest częścią pola, tzn. 'Csv' nie powoduje automatycznego przycięcia każdej wartości. Naprawiłem przykładowe dane i kod teraz działa Dziękujemy za zwrócenie uwagi na to pytanie: –

3

Możesz użyć modułu shlex, aby przeanalizować ciąg znaków.

Domyślnie shlex.split będzie podzielić na ciąg białych znaków nie ujętych w cudzysłów:

>>> shlex.split(teststring) 
['48,', 'one, two,', '2011/11/03'] 

nie usuwa z łańcucha tylnego przecinków, ale blisko tego, co trzeba. Jeśli jednak dostosować parser rozważyć przecinek spacją, wtedy dostaniesz wyjście, które potrzebujesz:

>>> parser = shlex.shlex(teststring) 
>>> parser.whitespace 
' \t\r\n' 
>>> parser.whitespace += ',' 
>>> list(parser) 
['48', '"one, two"', '"2011/11/03"'] 

Uwaga: obiekt parser jest używany jako iterator dostać żetony jeden po jeden. W związku z tym list(parser) iteruje nad obiektem analizatora składni i zwraca łańcuch podzielony tam, gdzie jest to potrzebne.

+0

To się załatwia, ale nie jest" t tak dobre af to jako moduł csv. –

23

csv module będzie działać, jeśli ustawić opcje do obsługi tego dialektu:

>>> import csv 
>>> teststring = '48, "one, two", "2011/11/03"' 
>>> for line in csv.reader([teststring], skipinitialspace=True): 
    print line 


['48', 'one, two', '2011/11/03'] 
+3

+1: ładny połów, dla tego 'skipinitialspace'! Próbowałem zrozumieć dokumentację "csv", ale nie mogłem uzyskać danych wejściowych OP do pracy :) –

-1
import shlex 
teststring = '48, "one, two", "2011/11/03"' 
output = shlex.split(teststring) 
output = [re.sub(r",$","",w) for w in output] 
print output 
['48', 'one, two', '2011/11/03'] 
Powiązane problemy