Ich habe diese Saite

circle,4.5
square,3.1
circle,2.0
triangle,4.7,4.9
square,4.1
circle,4.3

Nehmen wir an, ich möchte den Namen der Form und die beiden Zahlen daneben erfassen. Ich habe es versucht und werde das Problem kommentieren, das ich darin habe:

>>> ma = re.search(r"(\w+)[,(\d+.\d+)]+", "Triangle,3.4,1.2")
>>> ma.group()
'Triangle,3.4,1.2'
>>> ma.group(1)
'Triangle'
>>> ma.group(2)  ##Why is this happening ???
Traceback (most recent call last):
  File "<pyshell#29>", line 1, in <module>
    ma.group(2)
IndexError: no such group

Ich denke, ich kann keine Erfassungsgruppen in eckige Klammern setzen?

2
Rafael Adel 6 Okt. 2012 im 17:38

3 Antworten

Beste Antwort

Eckige Klammern sind etwas Besonderes. Sie markieren alle Zeichen in ihnen als Zeichengruppe. Sie möchten entweder eine Zahl (\d), ein , Komma, einen . Punkt, eine ( öffnende Klammer oder eine ) schließende Klammer finden . Mit anderen Worten, die öffnende und schließende Klammer sind Teil der übereinstimmenden Zeichen, nicht bezeichnet eine Erfassungsgruppe.

Sie müssen hier überhaupt keine Zeichenklasse verwenden, sondern suchen nach einem spezifischeren Zahlenmuster, das von einem Punkt gefolgt von einer anderen Zahl begleitet wird. Verwenden Sie eine nicht erfassende Gruppe ((?:...)), um das Zahlenformat zusammen mit dem Komma so zu gruppieren, dass es sich wiederholenden Zahlengruppen entspricht:

r"(\w+)(?:,(\d+.\d+))+"

Leider wird dadurch immer noch nicht mehr als eine Gruppe für Sie erfasst. Reguläre Ausdrücke erzeugen niemals eine variable Anzahl von Gruppen. Wir haben hier nur zwei Gruppen definiert, das ist alles, was wir bekommen:

>>> import re
>>> ma = re.search(r"(\w+)(?:,(\d+.\d+))+", "Triangle,3.4,1.2")
>>> ma.groups()
('Triangle', '1.2')

Siehe Regex-Frage zur Parsing-Methodensignatur und Python-Regex-Wiederholung mit Erfassungsfrage für andere SO-Fragen, die unter diese Einschränkung fallen.

Ihr Format ist eigentlich sehr einfach, und Sie sind viel besser dran, wenn Sie überhaupt keine regulären Ausdrücke verwenden. Einfach durch das , Komma teilen und fertig:

>>> "Triangle,3.4,1.2".split(',')
['Triangle', '3.4', '1.2']
1
Community 23 Mai 2017 im 10:24

Die Verwendung von .split(',') ist der einfachste Weg. Wenn Sie jedoch Regex verwenden möchten, sollten Sie verwenden

ma = re.search(r"^([^,]+),([^,]+)(?:,([^,]+))?", "Triangle,3.4,1.2") 
1
Ωmega 6 Okt. 2012 im 14:47

Eckige Klammern haben eine besondere Bedeutung. Sie sollen Character class erstellen. Wenn Sie also capture groups in eckige Klammern setzen, bedeutet dies, dass Gruppe1 oder Gruppe2 oder Gruppe3 übereinstimmen. Es stimmt nicht überein Alle Gruppen in Kontinuität. Sie müssten anstelle der eckigen Klammer ein anderes capture group verwenden.

Für diesen Fall können Sie jedoch einfach split verwenden: -

>>> str = "Triangle,3.4,1.2"
>>> str.split(",")
['Triangle', '3.4', '1.2']
>>> 
>>> str = "circle,4.5"
>>> str.split(",")
['circle', '4.5']

>>> str.split(",")[0]
'circle'
>>> str.split(",")[1]
'4.5'

Gemäß Ihrer Regex: -

ma = re.search(r"(\w+)[,(\d+.\d+)]+", "Triangle,3.4,1.2")

Sie verwenden den Zeichensatz [,(\d+.\d+)], der mit - , oder (\d+.\d+) übereinstimmt.

Sie sollten es ändern in: -

ma = re.search(r"(\w+)(,(\d+.\d+))+", "Triangle,3.4,1.2")

In diesem Fall gibt es jedoch ein Problem:

Sie haben nur 3 Gruppen erstellt: -

group 0 -> complete match
group 1 -> `,1.2` (Outer bracket)
group 2 -> `1.2`  (Inner Bracket)

Sie erhalten 3.4 nicht, weil (,(\d+.\d+)) zuerst übereinstimmt - ,3.4 und dann ,1.2. Es werden also nur ,1.2 gespeichert.

1
Rohit Jain 6 Okt. 2012 im 13:48