Reguläre Ausdrucke

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.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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 :).
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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..
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hier mal ein Code-Grundgerüst, wie ich es mir vorstellen könnte:
http://paste.pocoo.org/show/124950/
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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!
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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... :oops: :( 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!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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!

Code: Alles auswählen

re.compile(r".*[\.\?\!",]$")
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.
problembär

get_sex() ... Uhh, aah, ok, see you ... :mrgreen:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

problembär hat geschrieben:get_sex() ... Uhh, aah, ok, see you ... :mrgreen:
:-D So make a better proposal! ;-)
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

get_gender, denn gender ist das grammatikalische Geschlecht, nicht sex. :)
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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.. :cry:

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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 :twisted:
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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...
Zuletzt geändert von CiveX am Donnerstag 25. Juni 2009, 17:43, insgesamt 2-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ja: {m,}
Das Leben ist wie ein Tennisball.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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.
Zuletzt geändert von CiveX am Donnerstag 25. Juni 2009, 17:59, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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.
CiveX
User
Beiträge: 34
Registriert: Samstag 23. Mai 2009, 11:48

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 ß.

:cry:
Antworten