Seite 1 von 2

Probleme mit RegEx...

Verfasst: Freitag 22. November 2002, 12:07
von 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

Re: Probleme mit RegEx...

Verfasst: Freitag 22. November 2002, 12:18
von Voges
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

@voges

Verfasst: Freitag 22. November 2002, 13:17
von x-herbert
@voges

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

x-herbert

Re: @voges

Verfasst: Freitag 22. November 2002, 13:44
von Voges
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

@Voges

Verfasst: Freitag 22. November 2002, 14:01
von 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

Re: @Voges

Verfasst: Freitag 22. November 2002, 14:23
von Voges
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(" ")

Verfasst: Freitag 22. November 2002, 15:01
von Milan
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.

@Milan

Verfasst: Freitag 22. November 2002, 15:21
von x-herbert
@Milan @Voges
Danke für die Infos...

... die Zeilen werde ich mal ausprobieren

Gruss x-herbert

Verfasst: Freitag 22. November 2002, 21:26
von hans
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

@hans

Verfasst: Freitag 22. November 2002, 22:09
von 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

@Milan

Verfasst: Freitag 22. November 2002, 22:17
von 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

Re: @Milan

Verfasst: Freitag 22. November 2002, 22:28
von Voges
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

@Milan

Verfasst: Freitag 22. November 2002, 22:52
von x-herbert
@Milan


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

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


Gruss x-herbert

Re: @Milan

Verfasst: Freitag 22. November 2002, 23:02
von Voges
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

Re: @Milan

Verfasst: Freitag 22. November 2002, 23:21
von hans
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

Re: @Milan

Verfasst: Freitag 22. November 2002, 23:57
von Voges
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

Verfasst: Samstag 23. November 2002, 10:12
von Milan
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... ;)

Verfasst: Samstag 23. November 2002, 11:04
von hans
@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

*

Verfasst: Dienstag 26. November 2002, 21:59
von x-herbert
... habe noch was im Netz gefunden...

Code: Alles auswählen

DecodeUnicodeString = lambda x: codecs.latin_1_encode(x)[0]
gruss x-herbert

Re: *

Verfasst: Dienstag 26. November 2002, 22:18
von Voges
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