Problem mit reg. Ausdruck

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Sanji
User
Beiträge: 12
Registriert: Donnerstag 17. August 2006, 15:32
Kontaktdaten:

Hallo.

Ich versuche, herauszufinden, wie oft eine bestimmte Funktion in einer Datei vorkommt. Dazu lese ich erst eine Funktionsbibliothek ein, um eine Liste der Funktionen zu erhalten, und walke dann durch ein Verzeichnis und prüfe pro Datei, wie oft jede Funktion darin vorkommt.

Zuerst habe ich das so geprüft:

Code: Alles auswählen

expr = re.compile("("+function+")\s*\\(",re.S|re.I)
Duch da ich auch Funktionen namens h() und p() habe, würde obiger Ausdruck ja auch testmich() matchen, wenn ich nach h\s*\\( suche.

Also wollte ich das Sonderzeichen b Verwenden, um es als Boundary vor den Funktionsnamen zu setzen:

Code: Alles auswählen

expr = re.compile("\b("+function+")\s*\\(",re.S|re.I)
Das bringt mir aber für jede Funktion 0 Treffer.

Code: Alles auswählen

expr = re.compile("\\b("+function+")\s*\\(",re.S|re.I)
Bringt mir wieder eine uanderen Wert.

Welche Variante ist denn jetzt richtig? \b oder \\b? Wenn \s funktioniert (tut es das?), müsste es ja \b sein.

Grüße,
Sanji
Sanji
User
Beiträge: 12
Registriert: Donnerstag 17. August 2006, 15:32
Kontaktdaten:

So, mit etwas Trial&Error und ein paar berenigten Bugs ergab sich, dass

Code: Alles auswählen

re.compile("\\b("+function+")\\s*\\(",re.S|re.I)
die funktionierende Variante ist.
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hi Sanji,

das Problem ist ganz einfach, dass re seine Sonderzeichen mit Backslashes fluchtet, Python aber auch.

Beispiel: Du möchtest das Verzeichnis "\nobody" suchen.
Wenn Du "\nobody" angibst, interpretiert das Python als linefeed+"obody", welches wiederum an re als Pattern übergeben wird.

Damit Python den richtigen String re.compile übergibt, kann man den Backslash fluchten: "\\nobody" übergibt nun and re.compile "\nobody".

Nun erkennt aber auch re.compile den Backslash als Fluchtzeichen und interpretiert "\n" als Sonderzeichen. Also musst Du das auch wieder fluchten: "\\\\nobody" übergibt "\\nobody" and re.compile, das es als "\nobody" richtig auswertet.

Statt nun "\\\\nobody" anzugeben kannst Du auch die Python-Formatierung durch einen raw-String umgehen, mit: sRaw = r"\\nobody"

In Deinem Fall:

Code: Alles auswählen

re.compile(r"\b"+function+"\s*\(",re.S|re.I)
Die Klammern brauchst Du nicht, wenn Du nur die Vorkommen zählen willst, die gruppieren nur die Ergebnisse.

Grüße,
Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten