2016-09-04 6 views
1

Ich versuche, die übereinstimmende Zeichenfolge in einer Zeichenfolge mithilfe von Regex in Python zu finden. Die string sieht wie folgt aus:python regex übereinstimmende Zeichenfolge finden

band 1 # energy -53.15719532 # occ. 2.00000000 

ion  s  p  d tot 
    1 0.000 0.995 0.000 0.995 
    2 0.000 0.000 0.000 0.000 
tot 0.000 0.996 0.000 0.996 

band 2 # energy -53.15719532 # occ. 2.00000000 

ion  s  p  d tot 
    1 0.000 0.995 0.000 0.995 
    2 0.000 0.000 0.000 0.000 
tot 0.000 0.996 0.000 0.996 

band 3 # energy -53.15719532 # occ. 2.00000000 

Mein Ziel ist es, die Zeichenfolge nach tot zu finden. So wird das angepasste String so etwas wie:

['0.000 0.996 0.000 0.996', 
'0.000 0.996 0.000 0.996'] 

Hier ist mein aktueller Code:

pattern = re.compile(r'tot\s+(.*?)\n', re.DOTALL) 
pattern.findall(string) 

jedoch der Ausgang gibt mir:

['1 0.000 0.995 0.000 0.995', 
'0.000 0.996 0.000 0.996', 
'1 0.000 0.995 0.000 0.995', 
'0.000 0.996 0.000 0.996'] 

Jede Idee von dem, was ich tue, falsch?

Antwort

4

Sie möchten nicht die DOTALL Flagge. Entfernen Sie es und verwenden Sie stattdessen MULTILINE.

pattern = re.compile(r'^\s*tot(.*)', re.MULTILINE) 

Dies entspricht alle Zeilen, die mit tot starten. Der Rest der Zeile wird 1.

Unter Berufung auf die documentation, Hervorhebung von mir in der Gruppe sein:

re.DOTALL

Machen Sie die '.' Sonderzeichen passen alle Zeichen überhaupt, einschließlich ein Newline ; Ohne dieses Flag wird '.' mit Ausnahme von newline übereinstimmen.

Beachten Sie, dass Sie dies ohne Regex leicht tun können.

with open("input.txt", "r") as data_file: 
    for line in data_file: 
     items = filter(None, line.split(" ")) 
     if items[0] == "tot": 
      # etc 
+0

Das ist mein Problem löst. Ich denke, ich bin verwirrt über 'DOTALL' und' MUTILINE'. Muss mehr darüber lesen. –

1

Sie verwenden re.DOTALL, was bedeutet, dass der Punkt "." wird alles akzeptiert, auch Zeilenumbrüche im Wesentlichen sowohl "tot" es und alles zu finden, die bis zum nächsten Newline folgt:

      tot 
    1 0.000 0.995 0.000 0.995 

und

tot 0.000 0.996 0.000 0.996 

Entfernen re.DOTALL soll Ihr Problem beheben.

Bearbeiten: Eigentlich ist das DOTALL-Flag nicht wirklich das Problem (obwohl unnötig). Das Problem im Muster ist, dass \ s + mit der Zeilenumbruch übereinstimmt. dass mit einem einzigen Raum zu ersetzen löst dieses Problem:

pattern = re.compile(r'tot (.*?)\n') 
+0

Ich denke, ich sollte "DOTALL" in "MULTILINE" ändern, wie @Tomalak vorgeschlagen –

+0

MULTILINE wird hier nicht benötigt, es sei denn, Sie würden^und $ verwenden, um Anfang und Ende einer Zeile jeweils zu entsprechen. Ich muss darauf hinweisen, dass @ Tomalaks Lösung sauberer ist. – mpurg

+0

Sie haben Recht. '\ s +' ist eigentlich das Problem hier. Ich denke, es bedeutet nur mehr als einen Whitespace. Danke für die Information. –

1

Die alternative Lösung re.findall Funktion mit spezifischen RegexMuster mit:

# str is your inital string 
result = re.findall('tot [0-9 .]+(?=\n|$)', str) 
print(result) 

Der Ausgang:

['tot 0.000 0.996 0.000 0.996', 'tot 0.000 0.996 0.000 0.996'] 
Verwandte Themen