2009-08-13 10 views
3

I ont des fichiers csv avec le format suivant:analyse syntaxique des fichiers CSV arrière

CSV FILE 
"a"    , "b"  , "c" , "d" 
hello, world , 1  , 2 , 3 
1,2,3,4,5,6,7 , 2  , 456 , 87 
h,1231232,3  , 3  , 45 , 44 

Le problème est que le premier champ a des virgules « » en elle. Je n'ai aucun contrôle sur la génération de fichier, car c'est le format dans lequel je les reçois. Existe-t-il un moyen de lire un fichier CSV en arrière, de la fin de la ligne au début?

Cela ne me dérange pas d'écrire un petit script python pour le faire, si je suis guidé dans la bonne direction.

+2

N'est pas un fichier CSV très bien formaté si le premier champ contient des délimiteurs sans aucune sorte de guillemets. – davewasthere

+1

Ce n'est pas CSV. Donc, vous ne pouvez pas utiliser de techniques d'analyse CSV. C'est un autre format qui arrive à avoir des virgules, mais n'est absolument pas CSV dans aucun sens du mot. S'il vous plaît arrêtez de l'appeler CSV. Appelez-le "CSV-like" ou "valeurs de virgule aléatoire". –

Répondre

15

La méthode de chaîne rsplit divise une chaîne à partir de la droite au lieu de la gauche, et donc il est probablement ce que vous cherchez (il faut un argument spécifiant la nombre maximum de temps à diviser):

line = "hello, world , 1  , 2 , 3" 
parts = line.rsplit(",", 3) 
print parts # prints ['hello, world ', ' 1  ', ' 2 ', ' 3'] 

Si vous souhaitez supprimer les espaces blancs de début et de fin de chaque élément dans votre liste fente, vous pouvez alors il suffit d'utiliser la méthode strip avec une compréhension de la liste

parts = [s.strip() for s in parts] 
print parts # prints ['hello, world', '1', '2', '3'] 
+1

qui a bien fonctionné, merci un paquet – dassouki

1

Vous pouvez toujours faire quelque chose avec regex, comme (perl regex)

#!/usr/bin/perl 

use IO::File; 

if (my $file = new IO::File("test.csv")) 
{ 
    foreach my $line (<$file>) { 
    $line =~ m/^(.*),(.*?),(.*?),(.*?)$/; 
    print "[$1][$2][$3][$4]\n"; 
    } 
} else { 
    print "Unable to open test.csv\n"; 
} 

(Le premier est une recherche avide, les 3 derniers ne sont pas) Modifier: posté code complet au lieu de simplement la regex

+5

http://xkcd.com/208/ –

1

Inversez d'abord la chaîne, puis traitez-la.

tmp = tmp [:: - 1]

1

De l'exemple que vous avez fourni, il semble que les "colonnes" sont de taille fixe. Le premier (celui avec des virgules) a une longueur de 16 caractères, alors pourquoi n'essayez-vous pas de lire le fichier ligne par ligne, puis pour chaque ligne qui lit les 16 premiers caractères (valeur de la première colonne), et le reste en conséquence? Une fois que vous avez chaque valeur, vous pouvez aller plus loin et l'analyser plus en détail (découper les espaces, et ainsi de suite ...).

+0

Je viens de le mettre en forme, pour votre plaisir visuel – dassouki

1

Ce n'est pas un fichier CSV, séparé par des virgules, c'est juste cela.

Comment pouvez-vous être certain que n'est pas:

CSV FILE 
"a"    , "b"  , "c" , "d" 
hello   , world , 1 , 2 , 3 
1    , 2  , 3 , 4 , 5,6,7,2,456,87 
h    , 1231232 , 3 , 3 , 45,44 

Si le fichier est comme vous l'indiquez alors le premier groupe doit être entouré par des guillemets, regarde comme si les noms de champs sont si étranges que les champs contenant des virgules ne sont pas. Je ne suis pas un fan de réparer les erreurs loin de leur source, je repousserais au générateur de données pour fournir CSV approprié si c'est ce qu'ils réclament c'est.

+0

Bon point, mais je suis sûr du format que je suis à 100% comme le dernier trois colonnes sont de type int. Nous recevons les fichiers tels quels. Nous n'avons aucun contrôle sur la génération. Enfer, je ne suis même pas sûr de ce qu'ils utilisent pour les générer – dassouki

+0

Une de mes citations préférées est "J'adore les normes informatiques ... il y en a tellement à choisir!" Ce qui manque, c'est que même après avoir choisi l'une des nombreuses normes, il y a un million de façons de l'arranger. Heureux de vous avoir trouvé une solution, j'ai bien aimé la solution Regex, mais ce serait coûteux pour le processeur (ancien programmeur Perl avec un faible pour regex). Bonne chance avec votre traitement! – Lazarus

0

Si vous attendez toujours le même nombre de colonnes et que seule la première colonne peut contenir des virgules, lisez simplement n'importe quelle colonne et concaténéz les colonnes excédentaires au début. Le problème est que l'interface est ambiguë, et vous pouvez essayer de contourner cela, mais la meilleure solution est d'essayer de faire réparer l'interface (ce qui est souvent plus difficile que de créer plusieurs patches ...).

0

Je suis d'accord avec mr beer. C'est un fichier csv mal formé.Votre meilleur pari est de trouver d'autres délimiteurs ou arrêter de surcharger les virgules ou une citation/échapper au champ non séparant des virgules

4

Je ne comprends pas très bien pourquoi vous voulez lire chaque ligne en sens inverse, mais vous pouvez le faire:

Peut-être qu'il a fait ressembler les champs de longueur fixe pour la clarté?
import csv 
file = open("mycsvfile.csv") 
reversedLines = [line[::-1] for line in file] 
file.close() 
reader = csv.reader(reversedLines) 
for backwardRow in reader: 
    lastField = backwardRow[0][::-1] 
    secondField = backwardRow[1][::-1] 
+0

Ça a bien fonctionné: D merci – dassouki

Questions connexes