Regex: Genaue Anzahl matchen

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
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Hallo,

Laut dem Regular Expression Howto sollte Folgendes ein Muster für einen String mit 15 alphanumerischen Zeichen sein, es matcht aber nicht:

Code: Alles auswählen

In [20]: pattern = re.compile(r'\w{15,15}', re.IGNORECASE)

In [21]: print pattern.match('kol06tsehv-id01')
None
Mit

Code: Alles auswählen

pattern = re.compile(r'\w*', re.IGNORECASE)
matcht es, ich würde aber gerne jeden Char auf die Bedingung prüfen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Das es keinen Match gibt liegt einfach daran, dass "-" kein alpha-numerisches Zeichen ist.

Und das "\w*" gibt auch keinen Match fuer den gesamten String, sondern nur "kol06tsehv".

Schau dir dir Dokumentation bezüglich REs noch mal an, und im besonderen das "^" und das "$".

Was du suchst ist wahrscheinlich das folgende:

Code: Alles auswählen

pattern = re.compile(r'^[\w-]{15,15}$', re.IGNORECASE)
Wobei man sich unter Umständen das ^ und $ sparen kann.
BlackJack

Das '-' ist weder Buchstabe noch Ziffer. Genau da hört Dein zweiter regulärer Ausdruck auf. Wenn das '-' mit drin sein soll, musst Du es auch im Ausdruck erwähnen.

Code: Alles auswählen

In [22]: pattern = re.compile(r'\w*', re.IGNORECASE)

In [23]: a = pattern.match('kol06tsehv-id01')

In [24]: a.group()
Out[24]: 'kol06tsehv'

In [25]: pattern = re.compile(r'[-\w]{15}', re.IGNORECASE)

In [26]: a = pattern.match('kol06tsehv-id01')

In [27]: a.group()
Out[27]: 'kol06tsehv-id01'
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

EyDu hat geschrieben:Das es keinen Match gibt liegt einfach daran, dass "-" kein alpha-numerisches Zeichen ist.
Ist natürlich einleuchtend, ich hatte das in der Doku falsch gelesen.

Code: Alles auswählen

pattern = re.compile(r'^[\w-]{15,15}$', re.IGNORECASE)
ist genau das, was ich suchte, ansonsten müßte ich nochmal auf die Länge des Matches prüfen.
Danke!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du brauchst nur einmal die 15 in den geschweiften Klammern.
re Dokumentation hat geschrieben:{m}
Specifies that exactly m copies of the previous RE should be matched; fewer matches cause the entire RE not to match. For example, a{6} will match exactly six "a" characters, but not five.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

mkallas hat geschrieben:ist genau das, was ich suchte, ansonsten müßte ich nochmal auf die Länge des Matches prüfen.
Nur noch so eine Idee von mir: Soll der "-" eine Trennung des Strings darstellen? Gegen den genannten Ausdruck zu testen wäre dann wohl kaum sinvoll, da auch "---------------" gematcht werden würde. In so einem Fall würde ich folgendes empfehlen:

Code: Alles auswählen

x = 'kol06tsehv-id01'
pattern = re.compile(r'^\w+-\w+$', re.IGNORECASE)
if len(x)==15 and pattern.match(x):
    print 'OK'
else:
    print 'HMPF'
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Vielleicht steht der Bindestrich aber auch immer an der gleichen stelle, dann kann man das noch etwas vereinfachen:

Code: Alles auswählen

re.compile(r'^[\w]{10}-[\w]{4}$', re.I)
Dann spart man sich die Längenprüfung.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

EyDu hat geschrieben:Nur noch so eine Idee von mir: Soll der "-" eine Trennung des Strings darstellen? Gegen den genannten Ausdruck zu testen wäre dann wohl kaum sinvoll, da auch "---------------" gematcht werden würde.
Also ist es doch noch ein wenig komplizierter:
'-' * 15 ist natürlich unzulässig
'-' an erster und letzter Stelle sollte auch nicht vorkommen, ansonsten gibt es aber leider noch Relikte, die mehr als einen Bindestrich aufweisen.
eine passende re müsste dann sein:

Code: Alles auswählen

pattern = re.compile(r'^(\w+-*\w+)+$')
Den Ignorecase kann man hier weglassen, da \w sowieso auf a-z und A-Z geht, habe ich gerade gemerkt. Dafür muß dann wieder die Länge des Strings begutachtet werden.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Wie wärs dann mit

Code: Alles auswählen

pattern = re.compile(r'^\w[\w-]{13}\w$')
Das Stellt sicher dass es nicht mit einem Bindestrich beginnt oder endet und dass die Länge 15 ist. Man kann zwar immer noch 13 Bindestriche einfügen, aber irgendwann ist mit dem Mustererkennen per Regular Expression schluss und man muss den String normal validieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten