2009-10-14 7 views
0

Parfois, j'ai besoin d'analyser la chaîne qui est CSV, mais j'ai des problèmes avec les comas cités. Comme ce code l'a démontré. J'utilise python 2,4python csv help

import csv 
for row in csv.reader(['one",f",two,three']): 
    print row 

avoir 4 éléments [ « un" », « f ' », « deux », « trois »] mais je voudrais obtenir ce [ « un « f » » , 'deux', 'trois'] ou 3 éléments même si j'essaie d'utiliser l'option quotechar = '' '(toujours selon la documentation par défaut), comment puis-je ignorer la virgule entre guillemets?

Editer: Merci à tous pour trouver des réponses, évidemment, je me trompe mon entrée pour CSV, et la fin, je parsé STRIG pour les valeurs clés (NOM, DESCR ...)

Ceci est entrée

NOM: "2801 châssis", Collation: "châssis 2801, Hw série #: xxxxxxx, Hw Révision: 6.0", PID: CISCO2801, VID: V03, SN: xxxxxxxxx

+1

s'il vous plaît fournir un échantillon de données réelles - il semble que vos données ne sont pas csv. – nosklo

Répondre

3

Vous pouvez obtenir la Module csv pour vous dire, nourrir seulement votre sortie désirée dans l'écrivain

In [1]: import sys,csv 

In [2]: csv.writer(sys.stdout).writerow(['one", f"', 'two', 'three']) 
"one"", f""",two,three 

In [3]: csv.reader(['"one"", f""",two,three']).next() 
Out[3]: ['one", f"', 'two', 'three'] 
+0

lorsque je tente avec mon entrée réelle sortie, je ne me désiré pas c'est STRIG NOM: "2801 châssis", Collation: "châssis 2801, Hw série #: xxxxxxx, Hw Révision: 6.0", PID: CISCO2801, VID: V03, SN: xxxxxxxxx – Ib33X

+2

Donc en réalité vos données ne sont pas CSV, mais dans une sorte de format de dictionnaire?Une liste de paires clé-valeur séparées par des virgules? –

6

en fait, le résultat que vous obtenez est correct-syntaxe CSV est erroné.

Si vous souhaitez citer des virgules ou d'autres caractères dans une valeur CSV, vous devez utiliser des guillemets entourant la valeur entière, et non des parties de celle-ci. Si une valeur ne commence pas par le guillemet, l'implémentation CSV de Python ne suppose pas que la valeur est quotée.

Ainsi, au lieu d'utiliser

one",f",two,three 

vous devriez utiliser

"one,f",two,three 
+0

Malheureusement, je n'ai pas le contrôle sur la chaîne d'entrée – Ib33X

+0

Ensuite, je crains que vous ne pouvez pas utiliser le module 'csv' out of the box, mais vous devez écrire votre propre lecteur de données. –

1

Votre chaîne d'entrée est pas vraiment CSV. Au lieu de cela, votre entrée contient le nom de la colonne dans chaque ligne. Si votre entrée ressemble à ceci:

NAME: "2801 chassis", DESCR: "2801 chassis, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 
NAME: "2802 wroomer", DESCR: "2802 wroomer, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 
NAME: "2803 foobars", DESCR: "2803 foobars, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 

Le plus simple que vous pouvez faire est probablement de filtrer les noms de colonnes d'abord, dans le fichier entier. Cela vous donnerait alors un fichier CSV que vous pouvez analyser. Mais cela suppose que chaque ligne a les mêmes colonnes dans le même ordre. Toutefois, si les données ne sont pas cohérentes, vous pouvez les analyser en fonction des noms. Peut-être cela ressemble-t-il à ceci:

NAME: "2801 chassis", PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx, DESCR: "2801 chassis, Hw Serial#: xxxxxxx, Hw Revision: 6.0" 
NAME: "2802 wroomer", DESCR: "2802 wroomer, Hw Serial#: xxxxxxx, Hw Revision: 6.0",PID: CISCO2801 , VID: V03 , SN: xxxxxxxxx 
NAME: "2803 foobars", VID: V03 ,PID: CISCO2801 ,SN: xxxxxxxxx 

Ou quelque chose. Dans ce cas, j'analyserais chaque ligne en recherchant le premier ':', séparer la tête de la colonne, puis analyser la valeur (y compris la recherche de guillemets), puis continuer avec le reste de la ligne. Quelque chose comme ceci (code complètement non testé):

def parseline(line): 
    result = {} 
    while ':' in line: 
     column, rest = line.split(':',1) 
     column = column.strip() 
     rest = rest.strip() 
     if rest[0] in ('"', '"'): # It's quoted. 
      quotechar = rest[0] 
      end = rest.find(quotechar, 1) # Find the end of the quote 
      value = rest[1:end] 
      end = rest.find(',', end) # Find the next comma 
     else: #Not quoted, just find the next comma: 
      end = rest.find(',', 1) # Find the end of the value 
      value = rest[0:end] 
     result[column] = value 
     line = rest[end+1:] 
     line.strip() 
    return result 
+0

Votre fonction échouera puisque ':' peut faire partie de la valeur (citée) (voir DESCR). Il pourrait être plus facile d'utiliser une expression régulière ici! –

+0

Il n'échouera pas à cause de cela, car il traite les valeurs entre guillemets séparément. Il ne regarde jamais dans la valeur citée pour un: –

+0

Mais il échouerait parce que j'ai oublié le ", 1" dans la scission, avait [0, fin] au lieu de [0: fin] dans un endroit, et renvoyais la valeur au lieu du résultat . Avec ces trois changements, cela fonctionne. Assez bon pour le code que je n'ai même pas essayé de courir. :) –