2017-02-05 29 views
0

Ich muss (viele) Informationen aus verschiedenen Textdateien extrahieren. Ich frage mich, ob es eine kürzere und effizientere Art und Weise als die folgende ist:beste Möglichkeit, Daten zu extrahieren mit re.compiler

Erster Teil: (N Zeilen lang)

N1 = re.compile(r'') 
N2 = re.compile(r'') 
. 
Nn = re.compile(r'') 

Zweiter Teil: (2N Zeilen lang)

with open(filename) as f: 
    for line in f: 
    if N1.match(line): 
     var1 = N1.match(line).group(x).strip() 
    elif N2.match(line): 
     var2 = N1.match(line).group(x).strip() 
    elif Nn.match(line): 
     varn = Nn 

Empfiehlst du, die re.compile vars (Teil 1) vom Teil 2 zu trennen? Was benutzt ihr in diesem Fall? Vielleicht eine Funktion, die den Regex als Argument benutzt? und rufe es jedes Mal an.

In meinem Fall ist N 30, was bedeutet, dass ich 90 Zeilen habe, um ein Wörterbuch mit sehr wenig oder gar keiner Logik zu versorgen.

+1

Im Allgemeinen, wenn Sie 'n' Dinge wollen, verwenden Sie eine * Liste *. – jonrsharpe

+0

die extrahierten Daten werden in Listen und Wörterbüchern gespeichert, aber warum eine Liste vor dem Extrahieren verwenden? –

+0

... weil Sie etwas kürzer und effizienter haben wollen, als 'n' kompilierte Regexes mit separaten Namen zu definieren? – jonrsharpe

Antwort

0

Ich werde dies versuchen, zu beantworten, ohne wirklich zu wissen, was Sie sind tatsächlich dort zu tun. Diese Antwort könnte Ihnen also helfen oder nicht.

Zuerst einmal, was re.compile tut ist einen regulären Ausdruck vorkompilieren, so dass Sie es später verwenden können und nicht jedes Mal kompilieren müssen, wenn Sie es verwenden. Dies ist vor allem dann nützlich, wenn Sie einen regulären Ausdruck verwenden, der mehrmals in Ihrem Programm verwendet wird. Aber wenn der Ausdruck nur ein paar Mal benutzt wird, dann ist es nicht wirklich von Vorteil, ihn im Voraus zu erstellen.

So sollten Sie sich fragen, wie oft der Code ausgeführt wird, der versucht, all diese Ausdrücke zu finden. Ist es nur einmal während der Skriptausführung? Dann können Sie Ihren Code vereinfachen, indem Sie die Ausdrücke einbetten. Da Sie die Übereinstimmungen für jede Zeile in einer Datei ausführen, macht das Vorkompilieren hier wahrscheinlich Sinn.

Aber nur weil Sie den Ausdruck vorkompiliert haben, heißt das nicht, dass Sie zu schlampig sein sollten und den gleichen Ausdruck zu oft finden sollten. Schauen Sie sich diesen Code:

if N1.match(line): 
    var1 = N1.match(line).group(x).strip() 

Unter der Annahme, eine Übereinstimmung vorhanden ist, wird dieses N1.match() zweimal ausführen. Das ist ein Overhead, den Sie vermeiden sollten, da passende Ausdrücke (abhängig vom Ausdruck) relativ teuer sein können, selbst wenn der Ausdruck bereits vorkompiliert ist.

Stattdessen ist es nur einmal passen, und dann das Ergebnis wieder verwenden:

n1_match = N1.match(line) 
if n1_match: 
    var1 = n1_match.group(x).strip() 

an Ihrem Code Sehen, Ihre regulären Ausdrücke auch mutally Exklusiv-oder zumindest Sie immer nur verwenden, das erste Spiel zu sein scheinen und Überspringe die restlichen. In diesem Fall sollten Sie sicherstellen, dass Sie Ihre Schecks bestellen, so dass die häufigsten Überprüfungen zuerst durchgeführt werden. Auf diese Weise vermeiden Sie, zu viele Ausdrücke auszuführen, die nicht übereinstimmen. Versuchen Sie auch, sie so zu ordnen, dass komplexere Ausdrücke seltener ausgeführt werden.

Schließlich sammeln Sie das Übereinstimmungsergebnis in separaten Variablen varN. An dieser Stelle stelle ich in Frage, was genau Sie dort tun, denn nach all Ihren if-Prüfungen haben Sie keine klare Möglichkeit herauszufinden, was das Ergebnis war und welche Variable zu verwenden ist. An diesem Punkt könnte es sinnvoller sein, sie nur in einer einzelnen Variablen zu sammeln oder bestimmte Logik innerhalb der Bedingungskörper zu verschieben. Aber es ist schwer zu sagen mit der Menge an Informationen, die Sie gegeben haben.

+0

Die meisten vorkompilierten REs würden einmal (oder zwei) pro Datei verwendet, aber das Skript wird jeden Tag für hundert Dateien ausgeführt. Ja. Sie schließen sich gegenseitig aus, wenn sie mit einer Zeile übereinstimmen, bin ich 100% sicher, dass diese Zeile keine weiteren Informationen enthält. Ich kenne die Dateistruktur, wenn ich also weiß, dass die letzte Zeile immer Daten enthält, die ich brauche, setze ich das re.match zuletzt. Am Ende der for, jede var wird 3 dicts füttern. Aus diesem Grund habe ich diese Vars dort. Das Hauptdict wird von mehr oder weniger 110 Dateien unterstützt. Ich weiß wirklich nicht, ob dies der beste Weg ist, um Daten aus mehr oder weniger strukturierten Texten zu erhalten. –

+0

Wenn das Skript mehrere Male ausgeführt wird, aber der Python-Prozess dazwischen läuft, dann hilft das Vorkompilieren der Ausdrücke nicht. – poke

0

Wie in re module documentation erwähnt, die reguläre Ausdrücke Sie gehen durch re Methoden zwischengespeichert werden: abhängig von der Anzahl der Ausdrücke, die Sie haben, so dass sie das Caching sich nicht nützlich sein könnten.

Das gesagt, sollten Sie eine Liste Ihrer Regexes machen, so dass eine einfache for-Schleife Ihnen erlauben würde, alle Ihre Muster zu testen.

regexes = map(re.compile, ['', '', '', '', ...]) 
vars = ['']*len(regexes) 
with open(filename) as f: 
    for line in f: 
    for i,regex in enumerate(regexes): 
     if regex.match(line): 
     var[i] = regex.match(line).group(x).strip() 
     break # break here if you only want the first match for any given line. 
+0

Beachten Sie, dass der Code von OP bei der ersten Übereinstimmung stoppt, während Ihre Schleife immer mit allen Ausdrücken übereinstimmt. – poke

+0

@poke Du hast recht, ich habe mein Beispiel aktualisiert. – Faibbus

Verwandte Themen