Wiederholungen in Regex

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.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Innerhalb eines Skripts zur Anzeige der IP habe ich folgenden Ausdruck:

Code: Alles auswählen

'\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}'
Ich habe mal gelesen, dass es eigentlich ausreicht, das Muster (also 1-3 stellige Zahl gefolgt von einem Punkt) einmal anzugeben und dann zu sagen wie oft es sich wiederholen soll (dreimal natürlich, denn das hinter der letzten Zahl kommt ja kein Punkt). Leider komme ich nicht darauf, wie ich das ausdrücken muss und wäre über Hilfe dankbar. :)

Sebastian

Das Skript: http://paste.pocoo.org/show/87905/
acoolon
User
Beiträge: 27
Registriert: Samstag 2. August 2008, 20:16

Hau mich wenns falsch ist, aber war das nicht einfach *3

http://www.amk.ca/python/howto/regex/re ... 0000000000

acoolon
BlackJack

@snafu: Was hast Du denn schon versucht? Ich meine Du weisst ja ganz offensichtlich schon wie man eine Ziffer auf 1 bis 3 Wiederholungen begrenzt.

@acoolon: Fühl Dich gehauen. ;-)
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:Was hast Du denn schon versucht? Ich meine Du weisst ja ganz offensichtlich schon wie man eine Ziffer auf 1 bis 3 Wiederholungen begrenzt.
Naja, Klammern drum gesetzt:

Code: Alles auswählen

'(\d[.]){3}'
Aber da wird nichts gefunden. :(

Offen gesagt fehlt mir die Doku über eine Wiederholung von mehreren Zeichen. Ich denke, das Rumprobiere führt zu nichts.
fred.reichbier
User
Beiträge: 155
Registriert: Freitag 29. Dezember 2006, 18:27

Hallo,

'(\d[.]){3}' passt z.B. nur auf 1.2.3. (beachte den Punkt am Ende ;)) - eine Zahl gefolgt von einem Punkt, und das dreimal.
Es geht bestimmt sauberer, aber z.B. r'(\d{1,3}(\.\d{1,3}){3})'' würde funktionieren:
eine bis drei Zahlen, gefolgt drei weiteren Zahlen, die jeweils hinter einem Punkt stehen ;)

Gruß Fred
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Lösung von Fred funktioniert:

Code: Alles auswählen

In [44]: s = 'bla 12.345.6.789 blupp'

In [45]: re.findall('(\d{1,3}([.]\d{1,3}){3})', s)[0][0]
Out[45]: '12.345.6.789'
Aber wirklich glücklich bin ich damit noch nicht...
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn ich greedy bin, bekomme ich zumindest den ganzen Ip-String als eines der Elemente zurückgeliefert:

Code: Alles auswählen

In [64]: s
Out[64]: 'bla 12.34.567.890 blupp'

In [65]: re.findall('[\d+.]*', s)
Out[65]: ['', '', '', '', '12.34.567.890', '', '', '', '', '', '', '']
Kann ich direkt im Regex sagen, dass leere Ergebnisse nicht zurückgeliefert werden sollen?
Zuletzt geändert von snafu am Dienstag 14. Oktober 2008, 12:03, insgesamt 2-mal geändert.
BlackJack

Schau mal was Du da noch alles findest:

Code: Alles auswählen

In [267]: re.findall(r'[\d+.]*', '1.2.3.4.5.6.7 . ... 42')
Out[267]: ['1.2.3.4.5.6.7', '', '.', '', '...', '', '42', '']
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Habe es noch etwas eingrenzen können:

Code: Alles auswählen

In [123]: re.findall('[\d+.]*\W', s)
Out[123]: ['1.2.3.4.5.6.7 ', '. ', '... ']
Weiter komm ich irgendwie nicht.
BlackJack

Ich denke r'\d{1,3}(?:\.\d{1,3}){3}' ist noch mit das einfachste um vier dreistellige Zahlen, die durch Punkte getrennt sind zu matchen. Eine Funktion zum nachbearbeiten brauchst Du aber in jedem Fall, weil der Ausdruck auch auf 999.999.999.999 zutrifft.

Bei r'[\d+.]*' überleg doch mal *genau* was Du da beschreibst. Die vielen leeren Zeichenketten bekommst Du ganz einfach weg, in dem Du den Ausdruck so änderst, dass er eben nicht mehr auf die leere Zeichenkette passt, die ja sozusagen zwischen jedem Zeichenpaar in einer Zeichenkette steht.

Nachtrag: In Zeichenklassen gelten andere Regeln -- da ist ein '+' einfach nur ein '+':

Code: Alles auswählen

In [315]: re.findall('[\d+.]*', '1+2-3')
Out[315]: ['1+2', '', '3', '']
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

snafu hat geschrieben:Die Lösung von Fred funktioniert:

Code: Alles auswählen

In [44]: s = 'bla 12.345.6.789 blupp'

In [45]: re.findall('(\d{1,3}([.]\d{1,3}){3})', s)[0][0]
Out[45]: '12.345.6.789'
Aber wirklich glücklich bin ich damit noch nicht...
Warum? Weil das letzte .789 auch gefunden wird? Dann benutze einfach nicht-gruppierende Klammern:

Code: Alles auswählen

>>> s = 'bla 12.345.6.789 blupp'
>>> re.findall('(\d{1,3}(?:[.]\d{1,3}){3})', s)
['12.345.6.789']
Gruß,
Manuel
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Jupp, ich denke der letztgenannte Vorschlag ist der schönste. Danke an alle Beteiligten. :)
helduel hat geschrieben:Warum? Weil das letzte .789 auch gefunden wird? Dann benutze einfach nicht-gruppierende Klammern:
Ich fand die Gruppierung an sich unnötig, wusste aber nicht wie ich sie wegbekomme bzw dass sowas relativ einfach geht. Regexes sind nicht wirklich meine Stärke...

Aber mal eine generelle Frage: Die Variante "dreimal Digits-Punkt und einmal Digits" ist tätsächlich schwieriger darzustellen als "einmal Digits gefolgt von dreimal Punkt-Digits"?

EDIT: Hier mal der Code mit kleiner Fehlerbehandlung, sollte jetzt also halbwegs benutzbar sein (falls es jemanden interessiert) : http://paste.pocoo.org/show/87972/
BlackJack

@snafu: Ich hoffe ich verderbe Dir jetzt nicht den ganzen Spass, aber das geht auch ohne externes `ping` und regulären Ausdruck:

Code: Alles auswählen

In [322]: socket.gethostbyname('www.heise.de')
Out[322]: '193.99.144.85'
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Absolut nicht. Mir war diese Möglichkeit nur nicht bekannt und ich dachte, wenn sich keiner meldet, gibt es da wohl nichts. ^^

Ist auch etwas internes für die eigene IP möglich? Ich wähle mich über ein DSL-Modem ein, falls das von Belang ist.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

snafu hat geschrieben:Aber mal eine generelle Frage: Die Variante "dreimal Digits-Punkt und einmal Digits" ist tätsächlich schwieriger darzustellen als "einmal Digits gefolgt von dreimal Punkt-Digits"?
Nö, nicht die Bohne:

Code: Alles auswählen

# Digits + 3x Punkt-Digits
re.findall('(\d{1,3}(?:[.]\d{1,3}){3})', s)
# 3x Digits-Punkt + Digits
re.findall('((?:\d{1,3}[.]){3}\d{1,3})', s)
Ist ja nur rumgedreht, aber sonst das gleiche.

Gruß,
Manuel
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

snafu hat geschrieben:Ist auch etwas internes für die eigene IP möglich? Ich wähle mich über ein DSL-Modem ein, falls das von Belang ist.
Folgendes sollte klappen:

Code: Alles auswählen

import socket
socket.gethostbyname(socket.gethostname())
# oder
socket.gethostbyname_ex(socket.gethostname())
Gruß,
Manuel
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Das gibt den Localhost (127.0.1.1) zurück. Der interessiert mich ja nicht. ;)
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Ok, dann schau mal hier nach. Da kannst du dir die IP via Interface-Namen herauskramen.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und woher weiß ich was mein ifname ist?
Benutzeravatar
roschi
User
Beiträge: 225
Registriert: Samstag 29. März 2008, 18:58
Wohnort: Thueringen, Deutschland
Kontaktdaten:

hallo!

es geht zwar bestimmt noch einfacher, aber es gibt server, die dir via http deine ip zurueckgeben:

Code: Alles auswählen

import urllib
f = urllib.urlopen("http://checkip.dyndns.org/")
print f.read()
f.close()
mfg
roschi
[size=117]Fuer Alle, die in Python einsteigen wollen, kann ich das Buch [url=http://abop-german.berlios.de/]A Byte of Python[/url] nur waermstens empfehlen![/size]
Antworten