2010-05-25 15 views
6

Ich muss nach Zeilen in einer CSV-Datei suchen, die in einer nicht abgeschlossenen Zeichenfolge mit doppelten Anführungszeichen enden.Regex zum Finden einer nicht abgeschlossenen Zeichenfolge

Zum Beispiel:

1,2,a,b,"dog","rabbit 

würde passen, während

1,2,a,b,"dog","rabbit","cat bird" 
1,2,a,b,"dog",rabbit 

wollte nicht.

Ich habe sehr begrenzte Erfahrung mit regulären Ausdrücken, und das einzige, was ich denke, ist könnte so etwas wie

"[^"]*$ 

jedoch, dass bis zum Ende der Zeile das letzte Zitat paßt.

Wie würde dies geschehen?

+1

Was ist mit "" a "bc" "oder" "a" "bc" "? – SLaks

+0

Angenommen, es gibt keine" Zwischen "Anführungszeichen (keine verschachtelten Anführungszeichen) –

Antwort

5

Unter der Annahme, dass die Anführungszeichen nicht maskiert werden können, müssen Sie die Parität der Anführungszeichen testen (stellen Sie sicher, dass es eine gerade Anzahl anstelle von ungeraden gibt). Reguläre Ausdrücke sind dafür hervorragend geeignet:

^(([^"]*"){2})*[^"]*$ 

Das wird alle Zeilen mit einer geraden Anzahl von Anführungszeichen übereinstimmen. Sie können das Ergebnis für alle Strings mit einer ungeraden Zahl invertieren. Oder Sie können einfach ein anderen ([^"]*") Teil am Anfang hinzufügen:

^[^"]*"(([^"]*"){2})*[^"]*$ 

Und falls Sie Zugang zu zögern Betreiber statt gierigen haben, können Sie verwenden, um einen einfacheren aussehenden Ausdruck:

^((.*"){2})*.*$   #even 
^.*"((.*"){2})*.*$  #odd 

Jetzt, Wenn Anführungszeichen maskiert werden können, ist das eine ganz andere Frage, aber der Ansatz wäre ähnlich: Bestimmen Sie die Parität von nicht-entdeckten Anführungszeichen.

+0

Sollte es nicht einige Fragezeichen in diesen letzten beiden Regexen geben? Aber ich würde empfehlen Gegen diesen Ansatz sogar * mit * widerwilligen Quantifizierern, aus dem Grund @SLaks erwähnt: potentielles Runaway-Backtracking.Ihr erste Ansatz sollte sicher sein, da kein Teil der Regex die gleichen Zeichen wie ein benachbarter Teil übereinstimmen kann - alles entspricht entweder einem Zitat oder ein Nicht-Zitat –

+0

@Alan: In Bezug auf Fragezeichen, hängt von Ihrem Regex-Dialekt ab Einige Regex-Dialekte verwenden '*?' als das zögernde Kleene clo Sicher, während andere verlangen, dass Sie der Regex Flags zuweisen, um dem Interpreter mitzuteilen, dass Kleene-Schließungen widerwillig sind. Andere mögen sie standardmäßig als widerwillig betrachten und müssen ausdrücklich als gierig bezeichnet werden. – Welbog

+0

Ich kenne keine Regex-Variante, die Quantoren standardmäßig nur widerwillig behandelt. PHP hat den Modifikator "U", der sie nur widerwillig macht, wenn Sie das Fragezeichen verwenden, um sie gierig zu machen. Viele Leute, darunter auch ich, glauben, dass das Feature ein Fehler war und dass Benutzer dringend davon abgehalten werden sollten, es zu benutzen. Welchen Nutzen es bringt, wird durch die Verwirrung mehr als aufgehoben. –

4

Unter der Annahme, dass die Saiten nicht " enthalten können, benötigen Sie eine Zeichenfolge übereinstimmen, die eine ungerade Anzahl von Zitaten hat, wie folgt aus:

([^"]*("[^"]*")?)*"

Beachten Sie, dass dies zu einem DDoS-Angriff anfällig ist.

Dies entspricht null oder mehr Sätze von nicht-quoted run, gefolgt von in Anführungszeichen gesetzten Strings.

+0

Warum wäre es anfällig für einen DDOS? –

+0

Es ist habe geschachtelt expandos http://msdn.microsoft.com/en-us/magazine/ff646973.aspx (Die andere Antwort ist auch anfällig) – SLaks

0

Um "verschachtelt ExpandOS" zu vermeiden:

egrep -v '^[^"]*("[^"]*"[^"]*)*[^"]*$' my_file 
+0

Das ist immer noch verschachtelt expando (Ein besserer Begriff wäre eine verschachtelte Wiederholung) – SLaks

+0

Ah, OK, ich habe das als "verschachtelte Klammern" gelesen. – DVK

1

Versuchen Sie dieses:

".+[^"](,|$) 

Dieses Zitat passt (überall in der Linie), (gierig) durch irgendetwas gefolgt aber andere zitieren Sie vor dem Ende der Zeile oder ein Komma.

Der Netto-Effekt ist, dass es nur Zeilen mit baumelnden Strings in Anführungszeichen trifft.

Ich denke, es ist sogar immun gegen verschachtelte Expandos-Attacken (wir leben in einer sehr gefährlichen Welt ...)

Verwandte Themen