2010-01-26 10 views
7

Ich schreibe einen Parser mit ply, die FORTRAN String-Literale identifizieren muss. Diese werden in einfachen Anführungszeichen zitiert, wobei das Escape-Zeichen aus doppelten Hochkommas besteht. d.h.Wie schreibe ich einen regulären Ausdruck, der einem String-Literal entspricht, wobei das Escape-Zeichen eine Verdoppelung des Anführungszeichen ist?

'I don''t understand what you mean'

ist eine gültige Zeichenfolge FORTRAN entkommen.

Ply nimmt die Eingabe im regulären Ausdruck. Mein Versuch funktioniert bisher nicht und ich verstehe nicht warum.

t_STRING_LITERAL = r"'[^('')]*'"

Irgendwelche Ideen?

Antwort

20

Ein Zeichenfolgenliteral ist:

  1. Ein offener Single-Zitat, gefolgt von:
  2. Eine beliebige Anzahl von Doppelgarngruppe Apostrophe und nicht-Apostrophe, dann
  3. Eine enge Apostroph .

So unsere Regex ist:

r"'(''|[^'])*'" 
+1

Ah die zen von regulären Ausdrücken, danke! – Brendan

+1

Dies scheint keine Escape-Sequenzen zu behandeln. – Cyoce

4

Sie wollen etwas wie folgt aus:

r"'([^']|'')*'" 

Diese besagt, dass die Apostrophe innerhalb von Ihnen entweder doppelte Anführungszeichen oder ein nicht haben kann Zitat Charakter.

Die Klammern definieren eine Zeichenklasse, in der Sie die Zeichen auflisten, die übereinstimmen müssen oder nicht. Es erlaubt nichts komplizierteres als das. Daher funktioniert der Versuch, Klammern zu verwenden und eine mehrstellige Sequenz ('') zu finden, nicht. Stattdessen entspricht Ihre [^('')] Zeichenklasse [^'()], d. H. Sie entspricht allem, was kein einzelnes Zitat oder eine linke oder rechte Klammer ist.

0

Es ist in der Regel einfach, etwas zu bekommen schnell und unsauber für bestimmtes Stringliterale Parsen, die Ihnen Probleme geben, aber für eine allgemeine Lösung können Sie einen sehr leistungsfähigen und kompletten regex für Stringliterale vom pyparsing module erhalten:

>>> import pyparsing 
>>> pyparsing.quotedString.reString 
'(?:"(?:[^"\\n\\r\\\\]|(?:"")|(?:\\\\x[0-9a-fA-F]+)|(?:\\\\.))*")|(?:\'(?:[^\'\\n\\r\\\\]|(?:\'\')|(?:\\\\x[0-9a-fA-F]+)|(?:\\\\.))*\')' 

Ich bin mir nicht sicher über signifikante Unterschiede zwischen FORTRAN String-Literalen und Python, aber es ist eine praktische Referenz, wenn nichts anderes.

0
import re 

ch ="'I don''t understand what you mean' and you' ?" 

print re.search("'.*?'",ch).group() 
print re.search("'.*?(?<!')'(?!')",ch).group() 

Ergebnis

'I don' 
'I don''t understand what you mean'