perl

In den Lektionen bisher haben wir immer von STDIN gelesen. das ist praktisch für kleine Filterprogramme. Oft will man aber direkt aus einem file lesen. Das geht wie folgt:
#!/usr/bin/perl -w
open(BLA,") {
  chomp;
  print "gelesene zeile: $_ ";
}
close(BLA);
Obiges script liest z.B. die Datei /etc/passwd. Dazu wird ihr der filehandle BLA zugewiesen, dieser ist jetzt das Äquivalent zu STDIN. (es existiert die Konvention dass man filehandles in Grossbuchstaben schreibt).

Das "or die" hinter open wird aufgerufen falls das open fehlschlägt. Der "die" Befehl beendet das Programm mit der angegebenen Fehlermeldung.

Das < beim open gibt an dass wir die Datei zum Lesen öffnen. Soll in eine Datei geschrieben werden würden wir > schreiben:
#!/usr/bin/perl -w
open(BLI,">blabla.txt") or die "das file kann nicht geschrieben werden";
print BLI "bla bla bla ";
close(BLI);
Dieses script schreibt die Zeile "bla bla bla" in das file "blabla.txt" im aktüllen Verzeichniss. Man beachte dass kein Beistrich zwischen BLI und dem Text den man mit print ausgeben will sein darf.

Wird die Datei mit
open(BLI,">>blabla.txt");
geöffnet so wird der Text an eine schon vorhandene blabla.txt angehängt. Ist diese Datei noch nicht vorhanden wird sie angelegt.

Neben files kann das open auch Programme starten und deren Ausgabe lesen oder in deren STDIN schreiben (leider nicht beides gleichzeitig):
open(BLA,"who|") or die "can not run who";
while() {
  chomp;
  @fields=split(' ');
  print join('|',@fields),"
";
}
close(BLA);
das open(BLA,"who|") starte das Programm und verbindet das filehandle BLA mit der Ausgabe des Programmes. analog dazu:
#!/usr/bin/perl -w
open(BLA,"|mail -s test fs\@mond.at") or die "can not execute mail programm";
print BLA "hallo du da";
close(BLA);
Obiges Program verschickt eine Mail in dem das Programm "mail" aufgerufen wird. das | besagt dass unser filehandle BLA auf STDIN des aufgerufenen Programmes verbunden wird. Obiges Programm ist also dasselbe wie:
echo hallo du da | mail -s test fs@mond.at
Man beachte dass vor dem @ dieses "escape" notwendig ist, weil sonst der Perlinterpreter denkt man wollte das array mit dem Namen @mond hier einsetzen... eine gute Altenative ist statt der " " Anführungszeichen einfache Gänsefüsschen zu verwenden: 'fs@mond.at' ist eine Stringkonstante in der perl nicht versucht Stringersetzungen zu machen.



eine elegantere Methode Programme aufzurufen ist:
open(BLA,"|-") or exec "/usr/bin/mail" , "-s" , "test" , "fs@sil.at" ;
der Vorteil hier ist das der Aufruf von Programmen via exec sicherer ist und dass Perl das Programm direkt mit den angegebenen Parametern aufruft ohne Umwege über einen shell Interpreter.

Obige Beispiele funktionieren natürlich nur wenn die entsprechenden Programme existieren. Um mail auch auf Nicht-Unix System verschicken zu können gibt es Perl Module (davon später) die solche Funktionen abstrahieren..

#!/usr/bin/perl -w
opendir(HIER,".") or die "kann aktülles verzeichniss nicht lesen";
while($name=readdir(HIER)) {
  print "filename ist $name";
}
closedir(HIER);
Obiges script liest das directory "." und gibt alle darin gefundenen Filenamen aus. Ruft man den Befehl "readdir" in einem Kontext auf in dem als Ergebniss ein array erwartet wird so kann readdir alle Namen auf einmal lesen:
#!/usr/bin/perl -w
opendir(HIER,"/etc") or die "kann verzeichniss nicht lesen";
@allenamen=readdir(HIER);
closedir(HIER);
print join(",",@allenamen);
Obiges script gibt alle Filenamen aus dem /etc verzeichniss mit "," getrennt aus.

Zuletzt noch eine andere praktische Methode um Unix Kommandos aus Perl aus aufzurufen:
$datum=`date`;
$verzeichniss=`pwd`;
Obiges ruft den Befehl "date" und den Befehl "pwd" auf. Alternativ kann man schreiben:
$verzeichniss=qx/pwd/;


EXERCISES:

* Lies das file /etc/passwd und gib eine Liste aller user und ihrer Homeverzeichnisse aus.

* Verwende opendir, readdir um in obiger Liste auch noch die Anzahl der files anzugeben die sich (direkt) in dem Homeverzeichniss befinden. (Achtung: manche user lassen dich eventüll ihre Verzeichnisse nicht lesen)

* Verwende `` und du -s um die Summe des von den usern in ihren Homeverzeichnissen belegeten Plattenspeichers zu berechnen.

* Erweitere das script so dass es allen usern mit einer userid > 200 die mehr als 300000k an Diskspeicher belegen eine mail schreibt die mitteilt wieviel speicher belegt wurde..

REFERENCES:

man perlop
man perlfunc