2012-07-09 2 views
0
def csv_split() : 
    raw = [ 
      '"1,2,3" , "4,5,6" , "456,789"', 
      '"text":"a,b,c,d", "gate":"456,789"' 
      ] 
    cr = csv.reader(raw, skipinitialspace=True) 
    for l in cr : 
     print len(l), l 

Эта функция выходов следующие:CSV файл с цитируемой запятой не может быть корректно разделить на Python

3 ['1,2,3 ', '4,5,6 ', '456,789'] 
6 ['text:"a', 'b', 'c', 'd"', 'gate:"456', '789"'] 

Как вы можете сказать, первая линия правильно разделена на 3 записей. Но вторая строка НЕ. Я бы ожидал, что считыватель csv разделит его на на два, вместо этого у нас здесь 6. Я также думал о подходах regex , но он предполагает некоторый конкретный цитирующий диалект.

В принципе, я хочу: просто разделил строку всякий раз, когда есть «,», который не котируется в паре из «».

Есть ли какой-нибудь быстрый и общий способ для этого? Я видел некоторые хаки regex, которые предполагает, что все поданные ВСЕГДА цитируются и т. Д. Я думаю, что могу написать небольшую петлю , которая делает это очень неэффективно, но, безусловно, оценю еще экспертный совет. Большое спасибо!

+1

Это правильно разделив его. Данные CSV неверно отформатированы. Как вы думаете, что это должно быть разделено? –

+0

Вы должны сказать, что вы действительно хотите для второй линии, потому что я не могу понять, о чем вы просите. – Gabe

+0

@Gabe Я думаю, что OP ожидал '' "text": "a, b, c, d" и '" gate ":" 456,789 "'' - OP, пожалуйста, исправьте меня, если я неправильно понял. – Levon

ответ

2

CSV не является стандартизованным форматом, но обычно избегать кавычек, используя два "", если они появляются внутри текста (например, "text"":""a,b,c,d"). Читатель CSV от Python делает правильные вещи здесь, потому что предполагает это соглашение. Я не совсем уверен, что вы ожидаете от вывода, но вот моя попытка сделать очень простой CSV-ридер, который может подойти вашему формату. Не стесняйтесь приспосабливать его соответствующим образом.

raw = [ 
    '"1,2,3" , "4,5,6" , "456,789"', 
    '"text":"a,b,c,d", "gate":"456,789"', 
    '1,2, 3,' 
] 

for line in raw: 
    i, quoted, row = 0, False, [] 
    for j, c in enumerate(line): 
     if c == ',' and not quoted: 
      row.append(line[i:j].strip()) 
      i = j + 1 
     elif c == '"': 
      quoted = not quoted 
    row.append(line[i:j+1].strip()) 
    for i in range(len(row)): 
     if len(row[i]) >= 2 and row[i][0] == '"' and row[i][-1] == '"': 
      row[i] = row[i][1:-1] # remove quotation marks 
    print row 

Выход:

['1,2,3', '4,5,6', '456,789'] 
['text":"a,b,c,d', 'gate":"456,789'] 
['1', '2', '3', ''] 
+0

Извините за поздний ответ.Но да, что я хочу сказано выше: «„текст“:„а, б, в, г“,„ворота“:„456789“» следует разделить на две записи: [ «" текст ":" a, b, c, d "','" gate ":" 456,789 "']. Как я уже сказал, я просто хочу разбить, когда запятая не цитируется. Я согласен, что формат CSV немного испорчен. Но вы знаете, что я не могу контролировать то, что мне дают иногда. :( Спасибо за отличные ответы. Я попробую их и посмотрю, как наилучшим образом решить эту проблему. – user1510809

0

Оставляя это здесь для потомков, потому что я тоже боролся с этим немного.

Аргумент quotechar для csv.reader() помогает решить эту проблему; это позволит вам игнорировать делимы (т. е. запятые в этом сценарии), если они находятся внутри кавычек (при условии, что все запятые внутри записей были указаны). То есть, он будет работать для этого:

Name, Message 
Ford Prefect, Imagine this fork as the temporal universe. 
Arthur Dent, "Hey, I was using that!" 

... где запятая была вложена в кавычках, но без comma'd строка не имеет.

код Demo разорвал с Py2 docs и отредактированы так, чтобы delimiter запятая (дух) и quotechar это ваш двойной кавычки ":

import csv 
with open('eggs.csv', 'rb') as csvfile: 
    spamreader = csv.reader(csvfile, delimiter=',', quotechar='"') 
    for row in spamreader: 
     print ', '.join(row)