Seite 1 von 1

Problem mit reg. Ausdruck

Verfasst: Dienstag 22. August 2006, 14:49
von Sanji
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

Verfasst: Dienstag 22. August 2006, 15:36
von Sanji
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.

Verfasst: Dienstag 22. August 2006, 17:14
von Michael Schneider
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