Textverarbeitung mit Perl

Perl Praxis 8

In dieser Übung arbeiten wir mit Wortarten in der Form von POS-tags und lernen, wie man mit regulären Ausdrücken Muster erkennen kann.


Dieses Programm setzt in einem Text statt dem Wort "Hexe" das Wort "Thelma" ein.

Substitution Operator
#!/usr/local/bin/perl
#schreibt Thelma statt Hexe

# hexe-subs.pl FILE

    while (<>) {       #waehrend es noch Text gibt
     print	if  s/Hexe/Thelma/gi;  #wenn Hexe, stattdessen Thelma, drucken 
	  #    print "$_"; 
	       }

Übung 8.1. Kopiere oder tippe das Programm in einen Editor und probiere es mit hexe.txt aus. Wie sieht das Resultat aus?
Übung 8.2. Probiere es mit dem auskommentiertem print Kommando (das erste print muss natürlich auskommentiert werden). Was passiert jetzt?
Übung 8.3. Das Programm produziert z.Z. noch Sachen wie Thelmanhaus, was eigentlich nicht intendiert ist. Es soll ja nur jedes Vorkommnis des Wortes "Hexe" mit "Thelma" (oder einem anderen beliebigem Namen) ausgetauscht werden, aber da Thelma immer noch eine Hexe ist, soll sie auch weiterhin in einem Hexenhaus wohnen und aus einem Hexenbuch lernen. Ändere das Programm mittels des Wortankers \b, um dies sicherzustellen.
Übung 8.4. Schreibe das Resultat von 9.3. in eine Datei. Siehe dir die Datei an, um sicherzustellen, dass es auch wirklich funktioniert hat.


Dieses Programm durchsucht einen Text nach Wörtern, die verdoppelte Buchstaben enthalten, und druckt die entsprechende Zeile aus.

Reguläre Ausdrücke III
#!/usr/local/bin/perl
#druckt Zeilen aus, die Worte mit doppelten Buchstaben enthalten 

# double-lett.pl FILE

while (<>) {
    print if /([a-z])\1/  #doppelte Buchstaben 
    }

Übung 8.5. Kopiere oder tippe das Programm in einen Editor und probiere es mit hexe.txt aus. Wie sieht das Resultat aus? Was macht das "\1"?
Übung 8.6. Das Resultat wäre einfacher auszuwerten, wenn genau markiert würde, was gefunden wurde, und wo es gefunden wurde. Ändere erstmal das Programm, so dass es das Gesuchte (in runden Klammern, also $1, Memory Variable) zuerst ausdruckt, dann ein ": " folgt, und dann die Zeile, in der das Muster gefunden wurde ($_).
Übung 8.7. Jetzt wäre es noch schön, wenn das gefundene Muster etwas hervorgehoben würde. Ändere das Programm, so dass statt dem $_ erst das Material vor dem gefundenen Muster ($`), das gefundene Muster selber mit "+" Zeichen abgesetzt (+$&+), und dann das Material nach dem gefundenem Muster ($') ausgedruckt wird (alles auf einer Zeile, natürlich).
Übung 8.8. Schreibe ein weiteres Programm, dass nur die Zeilen herausucht, in denen es Worte gibt, die mit einem verdoppeltem Buchstaben enden (z.B. wundervoll). Hier ist der Wortanker \b gefragt.
Übung 8.9. Die Umlaute in hexe.txt sind als ae, ue, oe wiedergegeben. Es könnte sein, dass wir diese Schreibweise mal durch echte Umlaute ersetzen wollen. Such deshalb schon mal vorsorglich alle Worte heraus, die Umlaute haben. Wie sieht das Resultat aus? Ist auch unerwünschtes dabei?
Optional: Übung 8.10. Filtere die unerwünschten Resultate aus (vielleicht mittels einer stoplist?).
Übung 8.11. Schreibe ein weiteres Programm, dass Worte findet, die zwei oder mehr Sequenzen derselben Buchstaben enthalten. Z.B. Hexenkun+st++st+uecke oder Tann+en+zapf+en+. Hierzu muss man z.B. diesen regulären Ausdruck einbauen: /([a-z][a-z])\w*\1/.


Wortarten/POS-Tags

In der letzten Übung (Perl Praxis 7) haben wir funktionale Wörter per Hand (und ziemlich willkürlich) in einer stop list aufgelistet und dann die funktionalen Wörter in einem Text identifiziert. In dem folgenden Programm wird diese Idee aufgegriffen, aber diesmal benutzen wir Part-of-Speech-Tags (POS-tags) und durchsuchen einen automatisch annotierten Text: hexe-tag.txt, emerald-tag.txt. Um die Idee richtig umsetzen zu können, wird das gramzaehl.pl Programm mit Bigrammen kombiniert.

#!/usr/local/bin/perl
#errechnet das Verhaeltnis von funktionalen zu lexikalischen Worten in
#einem mit POS-tags annotiertem Text

#gramzaehl-tag.pl FILE

#einige POS fuer funktionale Woerter, in einer Liste
@gramlist = qw(ART KON VAFIN); 

#for English
#@gramlist = qw(EX DT CC); 

foreach $member (@gramlist) {
    $gramwords{$member} = 0;         #baue Hash von Liste
	}

$y = "\n";     #erstes willkuerliches Wort fuer Bigram 

while (<>) {    #waehrend es Input gibt 
    chop;
     foreach $wd (split) {    #fuer jedes Wort in einer Zeile
	 $z = $wd;            #tue in Variable fuer Bigram
	 if  ($wd =~ /[A-Z][A-Z]+/) {   #falls ein POS-tag
	    $gramwds++ if defined($gramwords{$wd});   #und falls funktional, zaehlen
	     $bigram{$x = "$y $z"}++;   #Hash fuer alle Wort+POS Folgen
		}  #if Ende
	 $y = $z;    # naechstes Wort fuer Bigram  
	 }  #foreach Ende
}  #while Ende 

$words = keys(%bigram);            #alle Worte
$lextokens = $words - $gramwds;    #lexikalische Worte
$ratio = $lextokens/$gramwds;      #Verhaeltnis zueinander

printf "Es gibt %4d verschiedene Worte in dem Text, von diesen sind 
%4d funktionale Worte und %4d lexikalische Worte.\n", $words,
    $gramwds, $lextokens; 
printf "\nRatio = %4.2f\n", $ratio;

Übung 8.14. Kopiere oder tippe das Programm in einen Editor und probiere es mit hexe-tag.txt oder emerald-tag.txt aus. Siehe Dir die Datei(en) auch an, damit klar ist, wie diese Datei aufgebaut ist, und was in ihr steht.
Übung 8.15. Die Liste der POS-tags für funktionale Wörter ist noch unvollständig. Identifiziere weitere funktionale POS-tags im STTS Tagset (Deutsch) oder im Penn Treebank Tagset, erweitere die Liste der POS-tags im Programm und probiere es dann nochmal aus. Hat sich etwas geändert?
Übung 8.16. Der reguläre Ausdruck in der ersten if Schlaufe ist etwas unbeholfen. Überlege, was er ausdrücken soll und ändere ihn dann mittels der { } Notation, damit er etwas kompakter (und intelligenter) ist.
Übung 8.17. Eigentlich wäre es schön, wenn man die Liste der gefundenen funktionalen Wörter auch ansehen könnte. Ändere das Programm, so dass die funktionalen Wörter nicht nur gezählt, sondern auch gleich in einem Hash abgespeichert werden (siehe gramzaehl.pl von oben). Im Unterschied zu gramzaehl.pl sollten jetzt aber nicht nur die Worte abgespeichert werden, sondern jedes Wort+POS Paar. Also muss jeweils das Bigram in den Hash getan werden. Nicht vergessen, den Hash mit den funktionalen Wörtern auch auszudrucken!
Übung 8.18. Nun sortiere noch die gesammelten funktionalen Wörter mittels sort by_number und drucke sie mit printf schön aus.



Dieses Program basiert auf en.pl aus Perl Praxis 7. Wir ziehen nun noch POS Information hinzu.

Wortarten
#!/usr/local/bin/perl
#findet Worte in einem getaggten Text, die auf -en enden

#en-adj.pl FILE

$y = "\n";   #erster Teil eines Bigrams  (Wort)

while (<>) {
    chop;
     foreach $wd (split) {  
	 $z = $wd;      #zweiter Teil eines Bigrams (POS-tag)
	 if ($y =~ (/en\b/))  { #falls finales -en 
             $enwords++;        #zaehlen
	     $enbigram{$x = "$y $z"}++;  #in Hash mit POS tag tun
			      }   #if fertig
	 $y = $z;                 # naechstes Wort
     }
}

printf "Es gibt %2d Worte, die mit -en enden.\n", $enwords; 

Übung 8.19. Kopiere oder tippe das Programm in einen Editor und probiere es mit hexe-tag.txt oder emerald-tag.txt aus. Wie sieht das Resultat aus?
Übung 8.20. Erweitere das Programm, so dass auch die Worte die mit ge, bzw. re anfangen, in eine Hashtabelle getan werden. Drucke auch den Inhalt dieser Tabelle zur Kontrolle aus.
Übung 8.21. Erweitere das Programm nun, so dass es nur die Worte mit en oder ed, die als Adjektive getaggt sind, aus der schon erstellten Hashtabelle heraussucht und diese wiederum in eine eigene Hashtabbelle tut. Dieser Teil des Programs sollte zum Beispiel mit foreach $w (keys %enbigram) { anfangen. Drucke den Inhalt dieser Tabelle zur Kontrolle aus. Bewerkstellige das gleiche für die Worte auf ge/re, mit dem Unterschied, dass hier nur die Verben herausgesucht werden sollen.
Übung 8.22. Erweitere das Programm nun noch weiter, so dass die Adjektive und Verben alphabetisch geordnet ausgedruckt werden. Der Output deines Programms sollte ungefähr so aussehen (das gleiche bezieht sich auf die Verben): Es gibt 69 Worte, die mit -en enden. Davon sind 7 Adjektive: ALPHABETISIERTE LISTE DER ADJEKTIVE


Diese Übung muss nicht eingereicht werden. Anja Leiderer hilft aber gerne bei Fragen.

Ende