Seite 1 von 2
Reguläre Ausdrucke
Verfasst: Mittwoch 24. Juni 2009, 18:27
von CiveX
Hallo,
mal wieder ich. Diesmal geht es um reguläre Ausdrucke.
Ich habe eine Textdatei. Darin sind halt normale Sätze wie z.B.
Ich fahre heute Auto , und bin glücklich dabei .
Usw. usf. die Leerzeichen zwischen den Satz- und Sonderzeichen sind absicht im Text, damit das einfacher wird.
Folgendes muss ich machen:
1) Extrahieren der Nomen
2) Anfügen des Geschlechts an das jeweilige Nomen
3) Sortiert Ausgeben
Die Kriteria zur Genauigkeit der Nomen- und Geschlechtserkennung spielt erstmal keine Rolle.
Das Erkennen der Nomen geht z.B. indem ich jedes Wort prüfe ob das 1. Buchstabe Groß oder Klein ist. Natürlich fallen dann Fehlerhafte dazu wie "Das" "Ist" "Ob" "Müssen", das ist aber egal erstmal.
Nachdem ich die Nomen erkannt habe, muss ich dann dem Nomen das Geschlecht zuordnen.
Hier dachte ich z.B. Endungsorientiert zu arbeiten.
Lehrerin, Freundin, das -in weist auf Feminin hin. Nun muss ich "F", "N", "M" abhängig vom Nomen anfügen und schließlich sortiert ausgeben.
Die Ausgabe soll in etwa so aussehen:
Abend M
Abende M
Abends M
Abendtafel F
Abenteuer N
Abfälle M
Abfällen M
Abgrund M
Ablaufs M
Ablehnung F
...
...
Ich komme allerdings mit den regulären Ausdrücken überhaupt nicht klar.
match...search...findall...findit...
Den Anfang habe ich schonmal gemacht, aber weiter komme ich absolut nicht.
Code: Alles auswählen
# Modul zur Verwendung von reg. Ausdrücken
import re
# Set für das Nominalexikon
nominalexikon = set([])
# Korpus aus einer Datei einlesen
# (Sie muss sich im selben Verzeichnis wie die
# Programmdatei befinden...)
text = unicode(open('8malt12.txt','Ur').read(),'utf-8')
# Text wird in Wort-Tokens aufgesplittet
# tokens = text.split()
# Definition des reg. Ausdrücks für Nomen
Nomen_re = re.compile(r'[A-ZÖÄÜ]')
'''
Hier stehe ich voll auf dem Schlauch. Wie definiere ich nun ein Kriterium, dass in jedem Wort, egal welcher Länge,
die 1. Buchstabe gematcht wird ob es klein oder GROß ist?
'''
# Text wird durchsucht und der vorher definierter
# reg. Ausdrück wird gesucht
nominalexikon = Nomen_re.findall(text)
# Entfernen von doppelten Einträgen
nominalexikon = set(nominalexikon)
print nominalexikon
Ich wäre für jede Hilfe dankbar!
Verfasst: Mittwoch 24. Juni 2009, 18:54
von Hyperion
Also ich würde da anders vorgehen!
Nutze split() und trenne den Text in Wörter auf. (Satzzeichen kannst Du dann für jedes einzelne Wort per .strip(",.

!") o.ä. entfernen.
Dann prüfst Du mit "word".isupper() ob der Buchstabe groß war. Wenn ja eben ein append an eine Nomen-Liste.
Danach kannste dann die Liste durchgehen und über eine Funktion get_sex() das Geschlecht bestimmen. Dazu mußte Dir eben gewisse Regeln ausdenken.
Verfasst: Mittwoch 24. Juni 2009, 18:57
von CiveX
Hyperion, ich darf nicht!
Ich MUSS reg. Ausrücke verwenden.
btw. falls Fragen auftauchen. Das ist eine Computer-Linguistische Aufgabe ich die, wegen Krankheit, nicht machen könnte und nun nachholen muss.
Bringt mir zwar keine Noten und Punkte, da zu Spät, aber verstehen und richtig haben möchte ich des trotzdem

.
Verfasst: Mittwoch 24. Juni 2009, 19:10
von Hyperion
CiveX hat geschrieben:Hyperion, ich darf nicht!
Ich MUSS reg. Ausrücke verwenden.
Wieso nur gibt es bei Akademikern manchmal so unsinnige Einschränkungen? Naja gut, was solls ...
Ok, dann teste mal Deinen Regex. Du willst zwar Großbuchstaben, aber die Wörter bestehen ja aus mehr als einem Buchstaben:
Code: Alles auswählen
In [108] nomen = re.compile(r"[A-ZÖÄÜ][a-z]+")
In [109]: for word in words:
.....: if re.match(nomen, word):
.....: print word
.....:
.....:
Hier
Schlauch.
Wie
Kriterium,
Wort,
Buchstabe
Verfasst: Mittwoch 24. Juni 2009, 19:27
von CiveX
Hallo Hyperion,
das ist schonmal ein super Anfang für mich. Zumindest verstehe ich jetzt die Schreibweise des reg. Ausdrücken etwas besser.
[A-ZÖÄÜ], erster Buchstabe groß gefolgt vom [a-z]+ Rest im Wort!
Sauber, danke!
Ich habe mir in der Zwischenzeit Regeln überlegt, wie man Nomen besser klassifizieren könnte. Folgendes fällt mir ein:
Regel A: Alles was mit einem großen Buchstaben anfängt, was nicht hinter Satzzeichen steht, und bei drei nicht auf dem Baum ist wird als Nomen definiert
Regel B: Alles, was hinter Satzzeichen steht und nirgendwo anders im Text klein geschrieben vorkommt ist mit sehr hoher Wahrscheinlichkeit ein Nomen
Problem ist wieder die Implentierung dieser Regel durch reg. Ausdrücke. Ich hasse dies..
Verfasst: Mittwoch 24. Juni 2009, 20:20
von Hyperion
Hier mal ein Code-Grundgerüst, wie ich es mir vorstellen könnte:
http://paste.pocoo.org/show/124950/
Verfasst: Mittwoch 24. Juni 2009, 20:41
von CiveX
Interessant, Hyperion, allerdings verwendenst du Sachen die mir nicht bekannt sind. Die ich aber allerdings logisch nachvollziehen kann.
Mein derzeitiger Code sieht so aus:
http://paste.pocoo.org/show/124959/
Jetzt muss ich nun die Kriteria für Nomen genauer definieren, und Kriteria zum Genus anfügen erstellen.
Verfasst: Mittwoch 24. Juni 2009, 20:49
von Hyperion
Du brauchst bei einem set keine leere Liste als Parameter zu übergeben. Außerdem kümmert sich der Datentyp selber um Duplikate
Code: Alles auswählen
In [25]: nomina = set()
In [26]: nomina.add("Haus")
In [27]: nomina.add("Baum")
In [28]: nomina
Out[28]: set(['Baum', 'Haus'])
In [29]: nomina.add("Baum")
In [30]: nomina
Out[30]: set(['Baum', 'Haus'])
Damit kannste Deinen Code ein wenig "aufräumen".
Was genau ist Dir an meinem Code unbekannt? Vielleicht kann ich es Dir erklären.
Generell solltest Du auf jeden Fall das ganze in Funktionen verpacken. Sonst wird es auf Dauer unübersichtlich!
Verfasst: Mittwoch 24. Juni 2009, 21:38
von CiveX
Recht haste, Hyperion.
Was dein Code angeht, ich war zu schnell beim Tippen als beim schreiben. Den Code verstehe ich nach mehrmaligem durchlesen. Du arbeitest halt mit Elementen die ich noch nicht Behandelt habe in Computerlingustik aka def, __main__ und so Dinger.
Klar, ich benutze sowas auch, WENN ich darf und kann. In diesem Teil darf ich halt nicht und muss mit den bekloppten Reg. Ausdrücken arbeiten.
Umständlich und teilweise völlig unnötig. Aber was solls.
Weiter geht's an dem Code zur Nomen- und Geschlechtserkennung.
Zur besserer Nomenerkennung habe ich mir folgende Regeln überlegt:
Regel A: Alles was mit einem großen Buchstaben anfängt, was nicht hinter Satzzeichen steht, und bei drei nicht auf dem Baum ist wird als Nomen definiert
Regel B: Alles, was hinter Satzzeichen steht und nirgendwo anders im Text klein geschrieben vorkommt ist mit sehr hoher Wahrscheinlichkeit ein Nomen
Ich habe einen Kollegen angefragt, der genau wie ich es auch nacharbeiten muss:
Regex-Codes sind zur Erkennung von Wörtern mit großbuchstaben am Anfang: r"^[A_Za-zÄÖÜ]{1}", zur Erkennung von Token mit Satzzeichen (Satzzeichen am Ende des Token, um auch "..." zu finden: r"[.,:;!?'()" + r'"]$' und zur Erkennung von "Das" bzw. "das" r"[Dd]as"
Nimm einfach tur Worterkennung die Regex-Strings überprüfe folgendes:
1) wort matcht mit Großbuchstaben-Regex, vorgänger matcht *nicht* mit Satzzeichen-regex -> Wort in Lexikon
2) Wort matcht mit großbuchstaben-regex, vorgänger matcht mit Satzzeichen-Regex, das OWrt kommt aber klein geschrieben nciht im Textkorpus vor -> Wort in LExikon
3) Sonst -> Wort verwerfen
Wenn ich das nun implentieren könnte...

Naja, mal am Code rumprobieren und mit print gucken wie das ganze läuft.
Danke aber sehr soweit Hyperion, eine große Hilfe war das allerdings!
Verfasst: Mittwoch 24. Juni 2009, 21:55
von Hyperion
CiveX hat geschrieben:Du arbeitest halt mit Elementen die ich noch nicht Behandelt habe in Computerlingustik aka def, __main__ und so Dinger.
Naja, das sind eigentlich sehr elementare Bestandteile von Python. Habt ihr wirklich noch keine Funktionen behandelt? Ohne Funktionen zu proggen ist bei derartig komplexen Sachen auf Dauer unschön, nervig und vor allem einschränkend.
Klar, ich benutze sowas auch, WENN ich darf und kann. In diesem Teil darf ich halt nicht und muss mit den bekloppten Reg. Ausdrücken arbeiten.
Naja, ich arbeite ja auch mit RegExps. Nur verpacke ich alles hübsch in Funktionen ... ist das wirklich verboten? Ändert ja am Grundprinzip nix
Ich habe einen Kollegen angefragt, der genau wie ich es auch nacharbeiten muss:
Regex-Codes sind zur Erkennung von Wörtern mit großbuchstaben am Anfang: r"^[A_Za-zÄÖÜ]{1}", zur Erkennung von Token mit Satzzeichen (Satzzeichen am Ende des Token, um auch "..." zu finden: r"[.,:;!?'()" + r'"]$' und zur Erkennung von "Das" bzw. "das" r"[Dd]as"
Hm ... also ersterer sieht mir falsch aus! Da funzt "unserer" doch besser. Auch die Satzzeichen sehen irgend wie krude aus ... da muss man doch imho mehr escapen!
Klappt bei mir jedenfalls für diese Zeichen (musst ggf. noch welche ergänzen)
Nimm einfach tur Worterkennung die Regex-Strings überprüfe folgendes:
1) wort matcht mit Großbuchstaben-Regex, vorgänger matcht *nicht* mit Satzzeichen-regex -> Wort in Lexikon
2) Wort matcht mit großbuchstaben-regex, vorgänger matcht mit Satzzeichen-Regex, das OWrt kommt aber klein geschrieben nciht im Textkorpus vor -> Wort in LExikon
3) Sonst -> Wort verwerfen
Klingt vernünftig. Naja, so schwer sollte das nicht sein. Musst nur rausfinden wie man auf ein Wort "vor" dem aktuellen zugreift. Außerdem Wort in Kleinschreibweise umwandeln (.tolower() iirc) und dann list.count(word) aufrufen. Bei 0 taucht es nicht auf.
Verfasst: Mittwoch 24. Juni 2009, 22:09
von problembär
get_sex() ... Uhh, aah, ok, see you ...

Verfasst: Donnerstag 25. Juni 2009, 06:21
von Hyperion
problembär hat geschrieben:get_sex() ... Uhh, aah, ok, see you ...


So make a better proposal!

Verfasst: Donnerstag 25. Juni 2009, 07:59
von Rebecca
get_gender, denn gender ist das grammatikalische Geschlecht, nicht sex.

Verfasst: Donnerstag 25. Juni 2009, 09:18
von CiveX
So, ich habe mal weiter an meinem Gerüst gebaut:
http://paste.pocoo.org/show/125014/
Text wird in Token gesplittet, jedes Token wird durchgangen und nach Nomen gematcht, daraus wird dann eine Nomenliste gebaut.
Nomenliste wird nun durchgangen, jedes Token in der Nomenliste wird nun nach match_m/f/n geprüft, falls match_m/f/n, dann wird das Token in Dictionary aufgenommen und am Token wird "F", "M" oder "N" angefügt, ansonsten wenn es keinen match gibt wird das Wort in Dictionary aufgenommen und ein [n.d.] (nicht definiert) angehängt.
Jetzt geht es an die Regel zur Nomenfilterung und Genusklassifikation erstellen. Zum Schluss dann Code optimieren..
Wie ich das Thema hasse...
PS: Die Regeln in nomen_f/m/n ignorieren. Habe ich auf die schnelle gemacht, um zu Testen ob das Gerüst funktioniert.
Verfasst: Donnerstag 25. Juni 2009, 11:47
von Hyperion
Rebecca hat geschrieben:get_gender, denn gender ist das grammatikalische Geschlecht, nicht sex.

Ok - dann haben wir das geklärt
Dennoch halte ich eine get_sex()-Funktion für eine Bereicherung eines jeden Quelltextes

Verfasst: Donnerstag 25. Juni 2009, 17:33
von CiveX
http://paste.pocoo.org/show/125112/
Code: Alles auswählen
# Definition des reg. Ausdrücks zur klassifizierung von Nomen
# Annahme: Nomen werden mit dem 1. Buchstaben groß geschrieben
nomen = re.compile(r'[A-ZÄÖÜ][a-zöäü]+')
Kann ich den reg. Ausdruck so ändern, dass er Wörter die max. 2 bzw. 3 Zeichen lang sind ignoriert und den rest aufnimmt??
Oder muss ich noch einen reg. Ausdruck erstellen.
Ich habs immer noch nicht so mit den Ausdrücken
Andere Frage:
Abwechslung F
Ablehnung F
aber
Zurückhaltung [n.d.]
Warum eigentlich? Ich habe ung als Endung für Feminin gemacht...
Verfasst: Donnerstag 25. Juni 2009, 17:37
von EyDu
Verfasst: Donnerstag 25. Juni 2009, 17:46
von CiveX
Das hilft mir jetzt nicht EyDu, da ich nicht verstehe WO.
nomen = re.compile(r'[A-ZÄÖÜ][a-zöäü]+')
Sucht ja jedes Wort, wo die 1. Buchstabe groß ist. Soweit, so gut.
Nun möchte ich aber zusätzlich noch, dass er dabei Wörter mit max. 2 Buchstaben (So, Ab, An, Am) bzw. 3 (Als, Dem, Den, Der, Die, Das) überspringt.
Klar fallen dabei auch Nomen Ruß, Sex, Aal, Aas, aber die sind vernachlässigbar.
Ich möchte also nomen = re.compile(r'[A-ZÄÖÜ][a-zöäü]+') erweitern. Geht das? Oder muss ich einen neuen Ausdrück formulieren?
Ich dachte an r'[A-ZÄÖÜ]{4,}[a-zöäü]+' aber das scheint nicht zu gehen. Wie du siehst, ich kapier die schreibweise der reg. Ausdrücken überhaupt nicht
Edit:
Okay, r'[A-ZÄÖÜ][a-zöäü]{3,}' funktioniert schon viel besser. Allerdings auch nicht ganz richtig.
Es werden zwar 2 und 3 Buchstabige Wörter gefiltert, aber auch:
Abfälle, Abfällen, Klänge, Klöster, Komödie, Kräfte, etc.
Wenn ich mir das richtig anschaue, alle Wörter die mehr als 3 Buchstabe haben, aber das 3. oder 4. Buchstabe ein äöüß ist, wird rausgeworfen.
Verfasst: Donnerstag 25. Juni 2009, 17:58
von Hyperion
Doku hat geschrieben:
{m,n}
Causes the resulting RE to match from m to n repetitions of the preceding RE, attempting to match as many repetitions as possible. For example, a{3,5} will match from 3 to 5 'a' characters. Omitting m specifies a lower bound of zero, and omitting n specifies an infinite upper bound. As an example, a{4,}b will match aaaab or a thousand 'a' characters followed by a b, but not aaab. The comma may not be omitted or the modifier would be confused with the previously described form.
Probiers doch mal in ner Shell aus! Fang mit einem kleinen RegExp an und erweitere den dann.
Verfasst: Donnerstag 25. Juni 2009, 18:22
von CiveX
Ja, das versuche ich ja gerade....
r'[A-ZÄÖÜ][a-zöäü]+'
Erster Buchstabe A-Z+ÄÖÜ gefolgt vom Rest in Kleinbuchstaben.
Laut Beispiel:
a{4,}b = aaaab aber nicht aaab oder aaab.
Okay dachte ich: Müsste dann ja einfach sein:
r'[A-ZÄÖÜ][a-zöäü]{4,}', also müsste das ja Wörter rausfiltern, die weniger als 4 Buchstaben haben.
Was ist? Es werden Wörter gefiltert mit 4 Buchstaben.Alles ab 5 Buchstaben wird aufgenommen. Hää?
Ok, dann ändern wir mal in r'[A-ZÄÖÜ][a-zöäü]{3,}', Ausgabedatei geguckt. Uii, klasse, schon viel besser.
Dann aktuelle Ausgabedatei mit alter Ausgabedatei geprüft, und was ist?
Abfälle, Abfällen, Klänge, Klöster, Komödie, Kräfte, etc. werden rausgeworfen, weil die zwar alle länger als 3 Buchstaben sind, ABER deren 3. bzw. 4. Buchstabe ist ein äöü oder ß.
