Probleme mit 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.
x-herbert

Hi, ich möchte einen "alleinstehenden" Sting finden und benötige einen Tipp für RegEx. z.B. soll eMailNews oder eMail-News nicht gefunden werden (key=eMail)...

.....................
key = "eMail"
i = ".....bla bla XXXX ..." #siehe unten XXXX...
regkey = "\\b"+key+"\\b" # finde key allein
regex = re.compile(regkey)
result = regex.search(i)
if result:
print "find"
else:
print "find not"
.......................
Ergebnis
XXXX: print:
eMail find # o.k. ;-)
eMailNews find not
eMail_News find not
eMail-News find # upps !!!!!!!!!!!!!!!!
eMail*News find # upps !!!!!!!!!!!!!!!!
eMail?News find # upps !!!!!!!!!!!!!!!!
eMail#News find # upps !!!!!!!!!!!!!!!!
...usw.


Danke!

X-herbert
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
x-herbert hat geschrieben:eMail_News find not
eMail-News find # upps !!!!!!!!!!!!!!!!
Das Verhalten ist ok. Aus der Doku zu \b: "A word is defined as a sequence of alphanumeric or underscore characters". Der Bindestrich ist also kein Wortzeichen.
Jan
x-herbert

@voges

wie müsste dann der Code aussehen, dass z.B. eMail-News nicht gefunden werden??

x-herbert
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!

Erstmal 'ne Rückfrage: Was verstehst Du in Deinem konkreten Fall unter "alleinstehend"? Eingeschlossen nur von Whitespaces (zzgl. String-Anfang und -Ende)? Wie sieht es mit Satzzeichnen aus?
"eMail-News"
"eMail,News"
"eMail, News"
"eMail(News)"
"eMail!!!!!"
Welches eMail ist davon "alleinstehend"?

Wie Alex in der Python-NG auf Dein Posting so schön schrieb: "but before we delve into such complications it MIGHT be better for you to clarify exactly what you need" ;-)

Jan
x-herbert

@Voges

mit "alleinstehend" meine ich, dass der String von einem Leerzeichen "umgeben sein darf, oder am Zeilen-Anfang/Ende...

Also bei Deinen Beispielen wäre nach "meiner Auffassung" keines der eMails "allein"

Gruss & Danke

x-herbert
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

x-herbert hat geschrieben:mit "alleinstehend" meine ich, dass der String von einem Leerzeichen "umgeben sein darf, oder am Zeilen-Anfang/Ende...
Dann würd' ich eine Lösung ohne Regexp favorisieren:

Code: Alles auswählen

text = "asdfadsf\neMail\tasdfasdf"
if "eMail" in text.split():
    print "gefunden"
else:
    print "nicht gefunden"
Jan

Nachtrag: Oops, Leerzeichen war nur gefragt. Dann muss es heißen: text.split(" ")
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

das funktioniert dann aber nur, wenn eMail auch als eMail geschrieben ist,bzw nur zwischen leerzeichen steht und nicht am Zeilenende, wie auch gewünscht... Wenn eMail als email geschrieben ist, funktioniert es nicht. Ich würde eher dein suchstring verändern:

Code: Alles auswählen

key="eMail"
regkey = "\s%s\s" % reduce(lambda x,y:x+"["+y+y.swapcase()+"]",key,"")
so wird zu jedem Buchtaben der eben andere (groß-->klein und umgekehrt gebildet) und das ganze in ein anderes Suchmuster eingebunden ("\s" heißst nach allem wie " \t\n\r\f\v" suchen, was ja das freistehend bedeuten würde.
Zuletzt geändert von Milan am Freitag 22. November 2002, 17:03, insgesamt 1-mal geändert.
x-herbert

@Milan @Voges
Danke für die Infos...

... die Zeilen werde ich mal ausprobieren

Gruss x-herbert
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Also die erste Version von x-Herbert finde ich ganicht so schlecht. Muß doch eigentlich nur der Compilerbefehl umgestellt werden.

Code: Alles auswählen

regex = re.compile(regkey, re.IGNORECASE)
result = regex.search(i) 
Quelle: http://py-howto.sourceforge.net/regex/node11.html

Hans
x-herbert

@hans

sieht soweit nett aus.... als code-snipp:

import re

key = "eMail"
s = ".....bla bla eMail?xx ..."
regkey = "\\b"+key+"\\b"
regex = re.compile(regkey, re.IGNORECASE)
result = regex.search(s)
if result:
print "find"
else:
print "find not"

>>> find

hmmm....

Gruss x-herbert
x-herbert

@Milan

Code: Alles auswählen

import re

key = "eMail" 
s = ".....bla bla eMail-xx ..." 
regkey = "\s%s\s" % reduce(lambda x,y:x+"["+y+y.swapcase()+"]",key,"")
regex = re.compile(regkey, re.IGNORECASE) 
result = regex.search(s) 
if result: 
    print "find" 
else: 
    print "find not"

>>> find not
... scheint die Sachen abzudecken, die ich mir vorstelle.... Danke!

x-herbert
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
x-herbert hat geschrieben:... scheint die Sachen abzudecken, die ich mir vorstelle....
Bei s = "eMail eMail" gibt es ein "find not", was sicherlich nicht erwünscht ist. Milans RegExp verlangt zwingend Whitespaces vorne und hinten.
Zudem: Auf r"\s[eE][Mm][aA][iI][lL]\s" nochmal re.IGNORECASE anzuwenden, ist doppeltgemoppelt. Mit IGNORECASE reicht r"\seMail\s".

Also, ich finde meine Lösung mit split() noch am besten (höhö). Wenn's aber unbedingt RegExps sein müssen:

Code: Alles auswählen

key = "eMail"
s = ".....bla bla eMail?xx  ..."
regkey = r'(?:^|\s)'+key+r'(?:$|\s)'
regex = re.compile(regkey, re.IGNORECASE)
result = regex.search(s)
Jan
x-herbert

@Milan


das "re.IGNORECASE" ist dann ja Quatsch...

entweder re.IGNORECASE oder die reduce/lambda-Version...


Gruss x-herbert
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
x-herbert hat geschrieben:das "re.IGNORECASE" ist dann ja Quatsch...
entweder re.IGNORECASE oder die reduce/lambda-Version...
Nur zur Klarstellung. Hans hatte re.IGNORECASE vorgeschlagen und zwar eben um Milans kompliziertes Konstrukt überflüssig zu machen. Das war vielleicht nicht klar geworden.
Jan
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Voges hat geschrieben:

Code: Alles auswählen

regkey = r'(?:^|\s)'+key+r'(?:$|\s)'
Hi Voges

kann nicht behaupten dass dein Code richtig oder falsch ist, dafür müßte ich ihn ersteinmal verstehen :? Ich habe dein Beispiel mal aufgelöst und komme zu folgendem Ergebnis:

Code: Alles auswählen

regkey='(?:^|\\s)eMail(?:$|\\s)'
Ist mir aber ehrlich gesagt immer noch unverständlich, obwohl ich etwas bewandert bin im Umgang mit grep, procmail und vi. Und RTFM hat mich auch nicht weitergebracht.

Hans
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
hans hat geschrieben:kann nicht behaupten dass dein Code richtig oder falsch ist, dafür müßte ich ihn ersteinmal verstehen :?
:-)
Also, das ?: ist in diesem konkreten Fall eigentlich überflüssig, hat für mich aber dokumentierenden Charakter.
regkey= r'(^|\s)eMail($|\s)'
Dann, denke ich, ist da schon klarer. (^|\s) steht für Stringanfang ODER Whitespace. Das ganze muss in Klammern stehen, damit klar ist, wo die beiden Alternativen anfangen und enden. Das gleiche Spiel nochmal für ($|\s).

Zum ?::
Im obigen Fall sind die runden Klammern nötig, um die ODER-Entscheidung zu ermöglichen. Andererseits nutzt man aber auch runde Klammern, um innerhalb von Regexps sogenannte Gruppen zu bilden.

Beispiel 1
Ich will eine Liste mit den Zahlen in den geschw. Klammern, die Klammern will ich aber nicht mit in der Liste haben:
s = "{4325} 23 {2343} 23 {4} 23 {}"
print re.findall(r'{(\d+)}',s) # --> ['4325','2343','4']


Beispiel 2
Ich will eine Liste mit den Zahlen in den geschw. Klammern und den Zahlen zw. "###"-Paaren:
s = "{4325} {2343} 34 ###4### 23"
print re.findall(r'(?:###|{)(\d+)(?:###|})',s) # --> ['4325', '2343', '4']


Das ?: ist nur ein Schalter, der verhindert, dass das Runde-Klammer-Paar zur Gruppierung herangezogen wird. Ohne diese ?: Schalter sähe die Liste so aus:
[('{', '4325', '}'), ('{', '2343', '}'), ('###', '4', '###')]

Jan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

danke Voges, den Fehler hab ich nich gesehn... aber ich musste trotz deiner Erklärung noch ein paar mal in der Syntax nachschlagen, eh ich's kapiert hatte... ;)
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

@Voges

Jetzt etwas verständlicher :? Ich muß da wohl noch etwas üben :!:

Ich bin aber auch etwas verwirrt. Ich dachte, dass re.search() immer nach ganzen Worten sucht, wobei ein Wort immer am Zeilenanfang steht oder mit Whitespace beginnt und immer am Zeilenende, mit Null oder Whitespace endet. (Kann sein, dass ich nicht alle Begrenzer genannt habe).

Wenn re.search() nur die reine Zeichenkombination sucht, kann ich dein Beispiel nachvollziehen. Wenn re.search() jedoch wortweise vergleicht, ist deine Suchfunktion etwas überfrachtet und würde nur Sinn machen, wenn man weitere Feldtrenner definieren will.

Hans
x-herbert

... habe noch was im Netz gefunden...

Code: Alles auswählen

DecodeUnicodeString = lambda x: codecs.latin_1_encode(x)[0]
gruss x-herbert
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
x-herbert hat geschrieben:... habe noch was im Netz gefunden...
Ich steh' etwas auf dem Schlauch. In welchem Zusammenhang steht das zum bisher Erörterten?
Jan
Antworten