Ich möchte verschiedene Teile einer Zeichenfolge abgleichen und sie zur späteren Verwendung in separaten Variablen speichern. Beispielsweise,

string = "bunch(oranges, bananas, apples)"
rxp = "[a-z]*\([var1]\, [var2]\, [var3]\)"

So dass ich habe

var1 = "oranges"
var2 = "bananas"
var3 = "apples"

So etwas wie das, was re.search () tut, aber für mehrere verschiedene Teile derselben Übereinstimmung.

BEARBEITEN: Die Anzahl der Früchte in der Liste ist vorher nicht bekannt. Hätte das mit der Frage einfügen sollen.

6
Arish 19 Nov. 2012 im 01:16

4 Antworten

Beste Antwort

Das macht re.search. Verwenden Sie einfach Erfassungsgruppen (Klammern), um auf die Inhalte zuzugreifen, die später von bestimmten Untermustern abgeglichen wurden:

>>> import re
>>> m = re.search(r"[a-z]*\(([a-z]*), ([a-z]*), ([a-z]*)\)", string)
>>> m.group(0)
'bunch(oranges, bananas, apples)'
>>> m.group(1)
'oranges'
>>> m.group(2)
'bananas'
>>> m.group(3)
'apples'

Beachten Sie auch, dass ich eine rohe Zeichenfolge verwendet habe, um die doppelten Backslashes zu vermeiden.

Wenn Ihre Anzahl von "Variablen" in bunch variieren kann, liegt ein Problem vor. Die meisten Regex-Engines können keine variable Anzahl von Zeichenfolgen erfassen. In diesem Fall könnten Sie jedoch damit durchkommen:

>>> m = re.search(r"[a-z]*\(([a-z, ]*)\)", string)
>>> m.group(1)
'oranges, bananas, apples'
>>> m.group(1).split(', ')
['oranges', 'bananas', 'apples']
4
Martin Ender 18 Nov. 2012 im 21:19

Tu es nicht. Jedes Mal, wenn Sie var1, var2 usw. verwenden, möchten Sie tatsächlich eine Liste. Leider ist dies keine Möglichkeit, mit findall eine beliebige Anzahl von Untergruppen in einer Liste zu sammeln, aber Sie können einen Hack wie diesen verwenden:

import re
lst = []
re.sub(r'([a-z]+)(?=[^()]*\))', lambda m: lst.append(m.group(1)), string)
print lst # ['oranges', 'bananas', 'apples']

Beachten Sie, dass dies nicht nur für dieses spezielle Beispiel funktioniert, sondern auch für eine beliebige Anzahl von Teilzeichenfolgen.

1
georg 18 Nov. 2012 im 21:22

Für reguläre Ausdrücke können Sie die Funktion match() verwenden, um das zu tun, was Sie möchten, und Gruppen verwenden, um Ihre Ergebnisse zu erhalten. Weisen Sie das Wort string nicht zu, da dies eine integrierte Funktion ist (obwohl sie veraltet ist). Wenn Sie beispielsweise wissen, dass jedes Mal die gleiche Anzahl von Früchten vorhanden ist, sieht dies folgendermaßen aus:

import re
input = "bunch(oranges, bananas, apples)"
var1, var2, var3 = re.match('bunch\((\w+), (\w+), (\w+)\)', input).group(1, 2, 3)

Hier habe ich die spezielle Sequenz \w verwendet, die mit jedem alphanumerischen Zeichen oder Unterstrich übereinstimmt, wie in die Dokumentation

Wenn Sie die Anzahl der Früchte nicht im Voraus kennen, können Sie zwei Aufrufe mit regulären Ausdrücken verwenden, einen, um den minimalen Teil der Zeichenfolge zu extrahieren, in der die Früchte aufgelistet sind, und "Haufen" und die Klammern entfernen, dann {{ X0}}, um die Namen der Früchte zu extrahieren:

import re
input = "bunch(oranges, bananas, apples)"
[m.group(0) for m in re.finditer('\w+(, )?', re.match('bunch\(([^)]*)\)', input).group(1))] 
2
acjay 18 Nov. 2012 im 21:35

Wenn Sie möchten, können Sie mit groupdict übereinstimmende Elemente in einem Wörterbuch speichern:

regex = re.compile("[a-z]*\((?P<var1>.*)\, (?P<var2>.*)\, (?P<var3>.*)")
match = regex.match("bunch(oranges, bananas, apples)")
if match:
    match.groupdict()

#{'var1': 'oranges', 'var2': 'bananas', 'var3': 'apples)'}
4
tehmisvh 18 Nov. 2012 im 21:33