|
| W. Wiedl: CGI- und PERL-Programmierung |
Zum Öffnen einer Datei dient das Kommando
open(FH,'Dateibezeichnung und Öffnungsmodus')Als File-Handles FH verwendet man üblicherweise Namen, die nur aus Großbuchstaben gebildet werden, das ist aber nicht zwingend. Im Regelfalle sollte das erste Zeichen eines File-Handles ein Buchstabe sein, danach dürfen beliebig viele Buchstaben und Ziffern folgen. Perl behandelt _ als Buchstaben.
Zum Schließen einer Datei verwendet man das Kommando
close(FH)meist verzichtet man jedoch auf das explizite Schließen einer Datei, dies erfolgt dann implizit durch den Perl-Interpreter bei Beendigung des Skript-Laufes oder bei erneutem Öffnen derselben Datei.
open(File-Handle,'Dateiname'); open(File-Handle,'<Dateiname');
Das Einlesen des Dateiinhaltes kann zeilenweise erfolgen. Mit:
$Zeile = <FH>;wird jeweils die nächste noch nicht gelesene Zeile eingelesen und der links stehenden Variablen als Wert zugewiesen. Man kann auch alle Zeilen auf einen Schlag lesen und sie als Werte einer Liste abspeichern:
@Zeilen = <FH>;Beispiel:
#!/usr/bin/perl open(STADT,'<../KURSDATEN/Eindaten.dat'); $Stadt = |
Anzumerken ist:
#!/usr/bin/perl
open(STADT,'<../KURSDATEN/Eindaten.dat')
|| die "Eingabedatei konnte nicht geöffnet werden";
$Stadt = |
chop($Satz);er entfernt das jeweils letzte Zeichen eines Satzes.
Was müssen wir nun beachten, wenn wir dieses Skript von einem Formular auf dem WWW-Server aus starten wollen?
<form method="post"
action="http://cgi.rrz.uni-hamburg.de/~rz2v003/KURS/Einaus.pl">
<input type=submit value="Skript starten">
</form>
|
Wir erhalten dann etwa:
#!/softsrv1/bin/perl
print "Content-type: text/plain\n\n";
open(STADT,'../KURSDATEN/Eindaten.dat')
|| die "Dateiöffnung gescheitert.";
$Stadt = <STADT>;
print $Stadt;
|
Offen ist dabei noch, worauf sich die Pfadangabe ../KURSDATEN/ in der Dateibezeichnung eigentlich bezieht. Hier gilt: Das Skript wird in dem Verzeichnis ausgeführt, in dem es steht. Das Skript und das Verzeichnis KURSDATEN haben also dasselbe Elternverzeichnis.
Das Skript funktioniert folgendermaßen:
open(File-Handle,'>Dateiname');wenn eventuell vorhandener Dateiinhalt überschrieben werden soll und mit:
open(File-Handle,'>>Dateiname');
wenn die neuen Formulareingaben jeweils an den vorhandenen Dateiinhalt angefügt werden sollen.
Die Ausgabe erfolgt mit der print-Anweisung:
print FH AusgabedatenGeschrieben wird damit in die aktuelle Ausgabezeile, Zeilenwechsel müssen in Perl immer explizit angegeben werden. Für Unix-Dateien ist dies das Zeichen 'newline', mit der Ersatzdarstellung \n. Man beachte, daß eingelesene Datenzeilen dieses Zeichen am Ende bereits enthalten.
Beispiel:
#!/softsrv1/bin/perl
open(STADT,'../KURSDATEN/Eindaten.dat')
|| die "Dateiöffnung gescheitert.";
$Stadt1 = <STADT>;
$Stadt2 = <STADT>;
print $Stadt1;
print $Stadt1,$Stadt2,"\n";
print $Stadt1,"\n",$Stadt2"\n";
print "$Stadt1 $Stadt2\n";
|
| 1 | LOCK_SH | shared read lock. Offener Zugriffsschutz, wird meist beim lesenden Zugriff verwendet. Andere dürfen während der Sperre die Datei lesen, schreiben darf jedoch nur der Benutzer, der die Sperre veranlaßt hat. |
|---|---|---|
| 2 | LOCK_EX | exclusive write lock. Exklusiver Zugriffsschutz, erlaubt anderen während der Sperre keinerlei Zugriff auf die Datei, auch keinen Lesezugriff. |
| 4 | LOCK_NB | nicht blockierende Sperre. Setzt lediglich einen Vermerk auf die datei ohne andere am Zugriff zu hindern. |
| 8 | LOCK_UN | unlock. Hebt eine Sperre wieder auf. |
Aufgabe 2:
Schreiben Sie ein HTML-Dokument mit einem Formular, das dieselben Daten abfragt wie das Formular aus Aufgabe 1. Das Formular soll aber diesmal nicht an FormMail, sondern an ein CGI-Skript mit Namen Aufgabe2.pl in Ihrem CGI-Verzeichnis geschickt werden. Schreiben Sie ein Perl-Skript, das die Antworten entgegennimmt und Sie zeileweise in der Form:
Parametername=Parameterwert
in einer Datei in Ihrem Home-Verzeichnis auf dem CGI-Server ablegt. Nachfolgende Formulareingaben sollen immer hinten an die vorhandenen angehängt werden. Ihr Home-Verzeichnis dort hat den absoluten Pfadnamen /cgi/Kennung, wobei Kennung für Ihre Benutzerkennung steht.
Die Formulareingaben sollen jeweils auch als normale Text-Datei an den WWW-Browser gehen. Abgesehen vom Abspeichern der Eingaben in einer Datei, soll Ihr Formular also so reagieren wie das nachfolgende:
#!/softsrv1/bin/perl open(LS," ls -l |"); while ($Zeile =Die Ausgabe des Unix-Kommandos 'ls -l' wird über den File-Handle LS zeilenweise eingelesen und auf die Standardausgabe ausgegeben. Das Kommando ls wirkt hier auf das Verzeichnis, in dem das Perl-Skript ausgeführt wird. Wenn also das Skript Pipe.pl heißt und im Verzeichnis: /cgi/rz2v003/cgi-bin/KURS steht und das momentane Arbeitsverzeichnis /cgi/rz2v003/cgi-bin/KURSDATEN ist, dann führt der Aufruf:) { print $Zeile; }
../KURS/Pipe.pldazu, daß das Inhaltsverzeichnis von /cgi/rz2v003/cgi-bin/KURSDATEN ausgegeben wird. Wenn das momentane Arbeitsverzeichnis dagegen: /cgi/rz2v003/cgi-bin/KURS ist, führt der Aufruf:
./Pipe.pldazu, daß der Inhalt von /cgi/rz2v003/cgi-bin/KURS ausgegeben wird. Wenn man das Skript von einem Formular aus aufrufen will, muß man noch den MIME-Type ausgeben lassen:
#!/softsrv1/bin/perl
print "Content-type: text/plain\n\n";
open(LS," ls -l |");
while ($Zeile = <LS>) {
print $Zeile;
}
Ausgegeben wird dann der Inhalt des Verzeichnisses, in dem das Perl-Skript steht.
Ebenso kann man auch einen Ausgabestrom in einen anderen Prozeß pipen. Im folgenden Beispiel wird ein Ausgabestrom an ein Drucke-Kommando weitergereicht:
#!/softsrv1/bin/perl
open(DR,"| lpr -Pps1");
while (<>) {
print DR $_;
}
Der angegebene Drucker muß definiert sein. Auf dem CGI-Server sind keine Drucker definiert.
Beispiel: Mail versenden
open(MAIL,"|mail ss8i000\@uni-hamburg.de"); print MAIL "Dies ist ein Test\n"; close(MAIL);Man beachte, daß hier der Klammeraffe maskiert werden muß, da er für sich selbst steht und keine Listennamen kennzeichnet.
Filehandles: Standareingabe: $a=<STDIN>;
chop($a = <STDIN>); gleich Newline abschneiden
while (<>) { .. } holt sich den Filenamen von der Eingabezeile; die Dateinamen kommen dabei in @ARGV
also könnte man auch folgendes machen:
@ARGV=("Datei1","Datei2","Datei3);
while (<>) { ... };
open(Filehandlename,"dateiname");
while($name=<Filehandlename>) {
chop($name);
print "$name\n";
}ein vorgesetztes -M gibt die Zeit in Tagen seit der letzten Speicherung
Bsp: if (-M Filehandlename >7) { .... } schon eine Woche herBsp: Eine komplette Datei ausgeben
open(Filehandle,"/etc/passwd");
while (<Filehandle>) {
chop;
print "$_\n";
}Bsp: Eine Datei kopieren
open(INFILE, "dateiname");
open(OUTFile,"outdateiname");
while (<INFILE>) {
print OUTFILE $_;
}
close(OUTFILE);
close(INFILE);Bsp: Alle Dateien holen
while ($nextname = </etc/host*.*>) {
print "$nextname\n";
oder while ($nextname = </etc/host*>) {$nextname = s#.*/##;
print "$nextname\n";
} alles von dem letzten / entfernen !Öffnen für Ausgabe:
open(AusgabeName,">dateiname");
print AusgabeName "Dies ist ein test\n";Wildcards:
while ($filename=<*.*>) {
print "ich habe $filename gefunden\n";
oder: @files=</etc/*.htm>; liefert alle *.htm-DateienEin ganzes Directory lesen:
opendir(ETCDIR, "/etc");
while ($name=readdir(ETCDIR)) { print "$name\n"; usw........}
closedir(ETCDIR);Datei umbenennen: rename($filename,"$filename.neu");
Datei löschen: unlink ("dateiname");
unlink (<*.html>); wie rm *.htmlDatei auf Existens testen: if (-e $filename) { ... $filename existiert };
Datei ist lesbar: if (-r $filename) { ... $filename ist lesbar };
Datei ist beschreibbar: if (-w $filename) { ... $filename ist schreibbar };
Anlegen eines Verzeichnisses: mkdir ("VerzName", 0777);
Hier eine Liste der Datei-Test-Zeichen -r lesbar
-w schreibbar
-x ausführbar
-o gehört dem Benutzer
-e existiert
-z existiert und hat die Größe Null
-s existiert und hat eine Größe
-f ist eine normale Datei
-d ist ein Directory
-l ist ein symb. Link-S ist ein Socket
-p ist ein FIFO
-b ist ein Festplatte
-c ist ein Zeichengerät
-t ist ein Ausgabegerät
-T enthält Text
-B enthält Binärdaten
-M Zeit seit der letzten Änderung in Tagen
-A Zeit seit dem letzten Zugriffes gibt noch weitere Löschen eines Verzeichnisses: rmdir ("verzname");
Zugriffsrechte ändern: chmod(0666,"dateiname");
Aufgabe3:
Schreiben Sie ein Perl-Skript, das die Eingaben des Formulares aus Aufgabe1 entgegennimmt und jeweils in eine eigene Datei in Ihrem Home-Verzeichnis auf dem CGI-Server ablegt. Der Dateiname soll gleich dem eingegebenen Nachnamen sein.Aufgabe4:
Schreiben Sie ein Perl-Skript, das von einem Formular den absoluten Pfadnamen eines Verzeichnisses auf dem CGI-Server übernimmt und die Namen aller Dateien in diesem Verzeichnis an den WWW-Browser übergibt.Aufgabe5:
Ändern Sie das Perl-Skript aus Aufgabe 4 so ab, daß die Dateiamen in einer Auswahlliste eines Formulares auf dem Bildschirm angeboten werden. Dateien, deren Namen mit . beginnen sollen nicht angeboten werden. Es sollen nur echte Dateien, also z.B. keine Verzeichnisnamen angeboten werden. Die ausgewählte Datei soll an das CGI-Skript: http://cgi.rrz.uni-hamburg.de/~rz2v003/KURS/Echo.pl geschickt werden.