Verstehe regular expression nicht...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

folgendes verstehe ich nicht:

Code: Alles auswählen

In [41]: re.match(r'(-?\d)?(.+)', '-12').groups()
Out[41]: ('-1', '2')

In [42]: re.match(r'(-?\d)?(.+)', '12').groups()
Out[42]: ('1', '2')

In [43]: re.match(r'(-?\d)?(.+)', '2').groups()
Out[43]: (None, '2')
[41] und [42] sind mir klar: (0 oder 1 '-' mit 1 digit) 0 oder 1 mal und danach (alle Zeichen 1 oder mehrmals).

Weshalb kommt bei [43] die '2' nicht in die erste Gruppe? Die einzige Erklärung für mich wäre, dass `re.match` die Zeichenkette von rechts nach links liest, was aber laut doc eigentlich nicht stimmen kann. Oder weshalb überwiegt die Bedingung der zweiten Gruppe vor der Bedingung der ersten?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Wenn die '2' in der ersten Gruppe wäre, dann wäre die zweite Gruppe leer, das darf sie aber nicht sein denn '.+' bedeutet *mindestens 1 Zeichen*. Wenn in der zweiten Gruppe nichts wäre, dann wäre es auch kein Match.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mutetella hat geschrieben:

Code: Alles auswählen

In [41]: re.match(r'(-?\d)?(.+)', '-12').groups()
Gruppe 1: *Vielleicht* eine einstellige Nummer mit vorangestelltem Minus (das Minus muss auf jeden Fall kommen).
Gruppe 2: Ein beliebiges Zeichen (oder mehrere davon).

Und die Treffer für die Gruppen verschieben sich nicht, sondern sind fest definiert. Wenn die erste Gruppe nicht matcht (z.B. wenn kein vorangestelltes Minuszeichen kommt), dann wird sie eben zu `None`.

Und nee, reguläre Ausdrücke werden an sich von links nach rechts gelesen. Das hat aber auch nichts mit der eigentlichen Problematik zu tun, sondern ist (nichts für ungut) ein nicht zutreffender Erklärungsversuch.

Um noch was hinterher zu schieben: Mir hat's dammalz (wie der Gelsenkirchener sagen würde) vor regulären Ausdrücken gegraut, da ich sie absolut nicht gecheckt habe. Inzwischen sehe ich sie als nützliches Hilfsmittel. Ab einer gewissen Komplexität würde ich allerdings Reckexen mit Python-Code vermischen, damit es noch halbwegs lesbar (und damit einhergehend auch wartbar) bleibt.

EDIT: Ups. Das Minus muss *nicht* in jedem Fall kommen. Da hatte ich was übersehen.
Zuletzt geändert von snafu am Sonntag 15. September 2013, 06:10, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du reguläre Ausdrücke wirklich vestehen willst, dann musst du dir die Theorie dahinter aneignen. Da findet nichts Magisches statt und übergebene Strings werden nach einem strengen Muster abgearbeitet. Im Prinzip reicht es aus wenn du nachliest, und es selber mal machst, wie aus einem regulären Ausdruck ein Automat gebildet wird. Du musst dir auch nicht gleich die volle Dröhnung mit minimalen deterministischen Automaten geben, bzw. die dazugehörigen Umformungsregeln.

Online sollte es dazu genug Information geben, auch fliegen sicher duzende Seiten rum, auf denen aus regulären Ausdrücken ein Automat erstellt wird, welchen du dir dann grafisch anschauen kannst.
Das Leben ist wie ein Tennisball.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

Dir fehlt noch der Fall, wo Du mit Deiner Erklärung gar nicht mehr weiter kommst:

Code: Alles auswählen

In [44]: re.match(r'(-?\d)?(.+)', '-1').groups()
Out[44]: (None, '-1')
aber auch hier liegt es einfach daran, dass die zweite Gruppe nicht leer sein darf und die erste, wenn vorhanden genau eine Zahl enthalten muß. Der Ausdruck ist akademisch dann zwar ganz nett, aber in der freien Natur nicht zu beobachten.
BlackJack

Ich habe für den Ausdruck mal einen Automaten gebastelt:

Code: Alles auswählen

                      re: (-?\d)?(.+)

          '-'                                        any
  +----------------+                               +-----+
  |                v                               v     |
+-------+  ''    +---+  digit   +-------+  any   #=========#
| 0 G1( | -----> | 1 | -------> | 2 G1) | -----> H 3 G2()  H
+-------+        +---+          +-------+        #=========#
  |       ''                      ^
  +-------------------------------+
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

snafu hat geschrieben:Ab einer gewissen Komplexität würde ich allerdings Reckexen mit Python-Code vermischen, ...
Versteh' ich jetzt nicht. Spätestens ab `import re` wird doch bereits vermischt...
Sirius3 hat geschrieben:Der Ausdruck ist akademisch dann zwar ganz nett, aber in der freien Natur nicht zu beobachten.
Das verunsichert mich jetzt ein wenig... Ich verwende den Ausruck für folgendes: Möchte der Nutzer eine monatliche Wiederholung erstellen, sagen wir jeden 2. Dienstag, so kann er das mit dem Argument `weekdays=2tu`. Den letzten Wochentag eines Monats definiert er durch `weekdays=-1fr`. Daneben besteht auch die Möglichkeit, Wochentage via Zahl zu bestimmen, die beiden Beispiele würden demnach `weekdays=21` bzw. `weekdays=-15` lauten. Fehlt links oder rechts, gibt's 'nen Fehler.
Soweit ich das bisher überblicke deckt der Ausdruck das ab.
BlackJack hat geschrieben:Ich habe für den Ausdruck mal einen Automaten gebastelt
Solche Sachen machen mich immer total kirre... :shock: :)

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: In der freien Wildbahn würde man dafür sorgen, dass die beiden Gruppen eindeutig voneinander getrennt sind, es also keine Eingabe geben kann die entweder in der einen oder der anderen Gruppe landet, oder gar etwas was eigentlich zusammengehört was in beiden Gruppen landet. Was Du hast ist eine (möglicherweise negative) *mehrstellige* Zahl die Optional ist, gefolgt von einem Namen. Also zum Beispiel r'(?P<number>-?\d+)?(?P<name>[a-z]+)?'. Jetzt hat man den Dingen Namen gegeben und wenn jemand eine 12 eingibt dann ist die in *einer* Gruppe und man muss sich die nicht aus zwei Gruppen zusammensammeln.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

mutetella hat geschrieben:
snafu hat geschrieben:Ab einer gewissen Komplexität würde ich allerdings Reckexen mit Python-Code vermischen, ...
Versteh' ich jetzt nicht. Spätestens ab `import re` wird doch bereits vermischt...
Ich meinte damit, dass ich Python-eigene Zeichenkettenoperationen wie `.split()`, `.strip()` und ähnliches bevorzugen würde, wenn ein äquivalenter regulärer Ausdruck komplizierter wäre als der besagte Python-Code. Ich gucke einfach, was ich für lesbarer halte und das nehme ich dann.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack: Da ist mal wieder der Magier mit mir durchgegangen. Ich fand's cool, dass die Position des Wochentags und der Wochentag selbst wie durch Geisterhand links-rechts getrennt wurden, eine alleinstehende einstellige Zahl rechts, Wochentagsname rechts.... OMG!!!
Du hast vollkommen recht!!! Gruppennamen sind super! Danke!

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten