2009-09-14 7 views
2

J'ai un fichier texte de type CSV qui compte environ 1000 lignes. Entre chaque enregistrement dans le fichier est une longue série de tirets. Les enregistrements se terminent généralement par un \ n, mais il y a parfois un \ n avant la fin de l'enregistrement. Exemple simplifié:Lookahead négatif après newline?

"1x", "1y", "Hi there" 
------------------------------- 
"2x", "2y", "Hello - I'm lost" 
------------------------------- 
"3x", "3y", "How ya 
doing?" 
------------------------------- 

Je veux remplacer le \ n supplémentaire est avec des espaces, à savoir concaténer les lignes entre les tirets. Je pensais que je serais capable de le faire (Python 2.5):

text = open("thefile.txt", "r").read()  
better_text = re.sub(r'\n(?!\-)', ' ', text) 

mais qui semble remplacer tous les \ n, pas seulement ceux qui ne sont pas suivies par un tiret. Qu'est-ce que je fais mal?

Je pose cette question dans le but d'améliorer mes propres compétences en regex et de comprendre les erreurs que j'ai commises. L'objectif final est de générer un fichier texte dans un format utilisable par une macro VBA spécifique pour Word qui génère un document Word stylé qui sera ensuite digéré par un CMS convivial.

+0

Si c'était Perl je dirais mettre $/'à ------------------------------- '' –

Répondre

5

Vous devez exclure les sauts de ligne à la fin des lignes de séparation. Essayez ceci:

\n(?<!-\n)(?!-) 

Cette expression régulière utilise un look-behind assertion négatif pour exclure \n qui est précédée par un -.

+0

Merci, je vois maintenant. Je n'ai pas réussi à définir le problème à fond avant d'essayer une solution, puis j'ai confondu les choses en supposant que je remplaçais tous les \ n quand je ne remplaçais que la moitié. – fwkb

1
re.sub(r'(?<!-)\n(?!-)', ' ', text) 

(Hyphen n'a pas besoin d'échapper à l'extérieur d'une classe de caractères.)

+0

... et en dehors d'une déclaration de plage de caractères et au début ou à la fin d'une classe de caractères. '[a-z-0-9]', '[-a-z]' et '[a-z-]' sont toutes les déclarations de classe de caractères valides. – Gumbo

7

C'est un bon endroit pour utiliser une fonction de générateur pour sauter les lignes de « s et donner quelque chose que le module csv Peux lire.

def readCleanLines(someFile): 
    for line in someFile: 
     if line.strip() == len(line.strip())*'-': 
      continue 
     yield line 

reader= csv.reader(readCleanLines(someFile)) 
for row in reader: 
    print row 

Cela devrait gérer les sauts de ligne entre guillemets de façon transparente et silencieuse.


Si vous voulez faire d'autres choses avec ce fichier, par exemple, enregistrer une copie avec les lignes supprimées, vous pouvez le faire.

with open("source", "r") as someFile: 
    with open("destination", "w") as anotherFile: 
     for line in readCleanLines(someFile): 
      anotherFile.write(line) 

Cela fera une copie avec les lignes supprimées. Cela n'en vaut pas vraiment la peine, car lire et ignorer les lignes est très, très rapide et ne nécessite aucun stockage supplémentaire.

+1

génial idée de dépouiller les lignes avec un générateur! – orip

+0

BTW - n'avez-vous pas besoin de len (line.strip()) au lieu de len (ligne)? – orip

+0

@orip: Ce serait un bug, merci. –

0

Un RegEx n'est pas toujours le meilleur outil pour le travail. Que diriez-vous de l'exécuter à travers quelque chose comme "Split" ou "Tokenize" en premier? (Je suis sûr que python a un équivalent) Alors vous avez vos dossiers et pouvez supposer que les nouvelles lignes ne sont que des suites.

Questions connexes