2017-04-26 2 views
4

Ich habe mehrere der Stack Overflow Beiträge mit ähnlichen Titeln angesehen, und keine der akzeptierten Antworten haben den Trick für mich getan.Match unescaped Zitate in zitierten csv

Ich habe eine CSV-Datei, in der jede "Zelle" von Daten durch ein Komma getrennt ist und zitiert wird (einschließlich Zahlen). Jede Zeile endet mit einem neuen Zeilenzeichen.

Einige Text "Zellen" haben Anführungszeichen in ihnen, und ich möchte Regex verwenden, um diese zu finden, so dass ich ihnen richtig entkommen kann.

Beispiel Linie:

"0","0.23432","234.232342","data here dsfsd hfsdf","3/1/2016",,"etc","E 60"","AD"8"\n 

Ich möchte passen nur die " in E 60" und in AD"8, aber keine der anderen ".

Was ist ein (vorzugsweise Python-freundlicher) regulärer Ausdruck, den ich dafür verwenden kann?

+0

*** https: //regex101.com/r/VxEXf2/3*** – 0m3r

+1

Vielen Dank für die Antwort! Das ist knapp, aber ich möchte nur diese internen Anführungszeichen anpassen, damit ich sie ersetzen kann (ich will zum Beispiel nicht den Teil "E 60" ersetzen. Ich denke, ich brauche auch den Rest der Zeichenkette) etwas flexibler als die Beschränkung auf einzelne Zahlen und Buchstaben in den anderen Strings (siehe aktuelles Original-Post-Beispiel) – sundance

+0

Können Sie das gewünschte Match auch aktualisieren – 0m3r

Antwort

1

BEARBEITEN: Mit Regex von @sundance aktualisiert, um Zeilen- und Zeilenumbrüche zu vermeiden.

Sie könnten versuchen, nur Zitate ersetzen, die zu einem Komma nicht weiter sind, Zeilenanfang oder Newline:

import re 

newline = re.sub(r'(?<!^)(?<!,)"(?!,|$)', '', line) 
+0

Ich habe 're.compile' verwendet, um es zuerst zu kompilieren, und dann die 'sub'-Methode auf der kompilierten Regex-Zeichenfolge.Sie konnte meine 4M-Zeilen-Datei in ungefähr 3-4 Minuten bereinigen – sundance

0

Anstatt regex, hier ist ein Ansatz, der String-Funktionen Python verwendet zu finden und Flucht nur Anführungszeichen zwischen den Anführungszeichen einer Zeichenkette links und rechts.

Es verwendet die .find() und .rfind() Methoden der Zeichenfolgen, um die umliegenden " Zeichen zu finden. Es ersetzt dann alle zusätzlichen " Zeichen, die in den äußeren Anführungszeichen erscheinen. Bei dieser Vorgehensweise werden keine Annahmen darüber getroffen, wo sich die umgebenden Anführungszeichen zwischen den Trennzeichen , befinden. Daher werden alle umgebenden Leerzeichen unverändert gelassen (z. B. wird '\n' am Ende jeder Zeile unverändert belassen).

def escape_internal_quotes(item): 
    left = item.find('"') + 1 
    right = item.rfind('"') 
    if left < right: 
     # only do the substitution if two surrounding quotes are found 
     item = item[:left] + item[left:right].replace('"', '\\"') + item[right:] 
    return item 

line = '"0","0.23432","234.232342","data here dsfsd hfsdf","3/1/2016",,"etc","E 60"","AD"8"\n' 
escaped = [escape_internal_quotes(item) for item in line.split(',')] 
print(repr(','.join(escaped))) 

in Resultierende:

'"0","0.23432","234.232342","data here dsfsd hfsdf","3/1/2016",,"etc","E 60\\"","AD\\"8"\n' 
+0

Dies kann komme zu der gleichen Antwort, aber es ist bestimmt weniger effizient als eine Regex-Engine, ich muss das auf 4M-Zeilen tun, also performe ce wäre ein Problem – sundance

+0

@sundance Danke für die Rückmeldung. Ich wusste nicht, wie groß deine Datei war. Ich lief Timings und finde, dass die Nicht-Regex-Lösung etwa doppelt so lange dauert (also etwa 8 Minuten für Ihre Datei). – Craig