ABSTRACT: perl: assoziative arrays (hashes) werden erklaert. AUDIENCE: perl beginners SYSTEM: any unix SECTION: perl AUTHOR: mond COPYRIGHT: GNU Free Documentation Licence http://www.gnu.org/licenses/fdl.txt eine besonders nuetzliche datenstruktur in perl sind sogenannte "assoziavive arrays" oder auch "hash arrays" oder kurz "hashes" genannt. wo ein normales array (kennen wir ja schon. z.b: $name[2]="alois" ) einen index hat der eine integer zahl ist kann ein hash array strings als index haben. also z.b.: $ort{"alois"}="hinterholz 8"; $ort{"anna"}="wien"; will man den ganzen hash auf einmal ansprechen so schreibt man % davo: %ort=(); obiges wuerde das hash array leer machen. wo normale arrays aufgrund ihres indexes ein natuerliche ordnung haben ( das element 0 ist das erste. dann kommt 1, 2, 3 usw.. .) gibt es bei assoziativen arrays keine ordnung. man kann damit natuerlich auch nicht mit push und pop etc darauf arbeiten. die einzige weg ist den index string (auch "schluessel" oder "key" genannt) wieder anzugeben: print "alois wohnt in ",$ort{'alois'},"\n"; es gibt jedoch eine funktion die alle schluessel eines hash arrays zuruecliefert: @allenamen = keys $ort; das array allenamen wuerde in diesem falle die werte "alois" und "anna" enthalten. die reihenfolge in der keys die schluessel zurueckliefert ist allerdings voellig undefiniert. (man koennte allerdings die funktion "sort" verwenden um die werte z.b. alphabetisch zu sortieren) versucht man mit einem schluessel zuzugreifen dem noch kein wert zugewiesen wurde so liefert das hash array den undefined zurueck. damit darf man nicht weiterrechnen weil man sonst einen fehler bekommt. man kann aber abpruefen ob der wert undefined ist. angenommen $ort{"franz"} existiert nicht: $wolebt=$ort{"franz"}; if (not defined $wolebt) { $wolebt="ort nicht bekannt"; } obiges laesst sich z.b. schoener mit einem "unless" schreiben als: $wolebt=$ort{"franz"}; $wolebt="ort nicht bekannt" unless defined $wolebt; um assoziative arrays mit vorgegebenen zuordnungen zu initialisieren kann man folgende schreibweise verwenden: %geburtsjahr=( "franz" => 1968, "babsi" => 1980 , "eva" => 1956 , "gabi" => 1960 ); damit ist z.b. folgende schleife moeglich: $heuer=2001; foreach $n (keys %geburtsjahr) { $alter=$heuer - $geburtsjahr{ $n } ; print "$n wird dieses jahr $alter jahre alt\n"; } wir wollen jetzt ein programm schreiben das zwei files (im selben format wie /etc/passwd ) liest und eine liste an namen ausgibt die in beiden files existieren aber unterschiedliche realnames haben und den jeweiligen realname ausgibt. (realname ist das 5te file im passwd file). #!/usr/bin/perl -w %realn=(); open(PF," ) { chomp; @pz=split(/:/); $username=$pz[0]; $realname=$pz[4]; $realn{$username}=$realname; } close(PF); open(PF," ) { chomp; @pz=split(/:/); $username=$pz[0]; if (defined $realn{$username} and $realn{$username} ne $pz[4]) { print "username $username existiert in beiden files\n"; print "im ersten: ",$realn{$username},"\n"; print "im zweiten: ",$pz[4],"\n"; } } close(PF); man beachte das "defined" um abzupruefen ob der schluessel im hash existiert und der stringverleich mittels "ne". if ($string1 ne $string2 ) { ne steht fuer "not equal". ("eq" waere equal. "lt" waere less then "le" waere less or equal, ..) zum vergleichen von zahlen verwendet man aber die normalen vergleichsoperationen < > <= >= ... EXERCISES: * schreibe ein script das zwei passwort files vergleicht und eine liste aller usernamen ausgibt die in jeweils einem der beiden files nicht vorhanden sind. * schreibe ein script das alle woerter die laenger als 2 buchstaben sind aus einem textfile einliest und mitzaehlt wie oft jedes der worte vorkommt. am ende soll eine liste ausgebeben werden die enthaelt wie oft jedes wort vorgekommen ist. (die zahl der vorkommnisse soll intern in einem hash array gespeichert sein) REFERENCES: man perldata