| Auf dieser Seite finden sie Hinweise und Beispiele zum Lesen und Schreiben von Dateien mit Perl. |
Perl
|
Scripts für CGI und Systemverwaltung |
| Text lesen | Text-Dateien lesen und verarbeiten |
| Text schreiben | Text-Dateien schreiben |
| Zugriffs-Rechte | Lesen, Schreiben, Ausführen: Programm-Generator mit Perl |
| Standard-Kanäle | <STDIN> <STDOUT> sind immer geöffnet. |
| Umleitung | Umleitung an und von Dateien, Variablen oder 'ins Leere' |
| Perl Module | Zusatz-Module zum Lesen & Schreiben von Dateien |
| Verwandte Themen auf anderen Seiten | |
| Binär lesen | Binär-Dateien lesen und verarbeiten |
| Binär schreiben | Binär-Dateien schreiben |
| Random Access | An beliebigen Datei-Adressen Lesen oder schreiben |
| Webseiten lesen | Live-Webseiten lesen und Informationen entnehmen |
| Operatoren | Informationen über Verzeichnisse und Dateien |
| Pipes | Kommunikation zwischen Prozessen |
| Datei-Baum | Durchforsten eines ganzen Datei-Baums (tree) |
Text-Dateien lesen und verarbeiten |
|
open()File-Input & Output (I/O) beginnt mit dem Öffnen der gewünschten Datei.► Funktion open() benötigt 2 Argumente: HANDLE und $path ► HANDLE ist ein Symbol-Name für die geöffnete Datei. Der Name kann beliebig gewählt werden und wird üblicherweise in großen Buchstaben geschrieben. ► $path ist ein String, der aus 2 Teilen besteht: mode und dem eigentlichen Pfad inkl. Dateiname. Auch Windows-Pfade kann man mit dem Standard-Trennzeichen / formulieren. (Alternativ müssen sie \ Backslash-Trennzeichen mit zusätzlichen \ maskieren). ► Standard-(default)-mode ist 'Lesen' ( < oder read ), daher wird für das Lesen normalerweise der mode weggelassen. ► Sie können gleichzeitig mehrere Dateien öffnen. Wählen sie in diesem Fall unterschiedliche HANDLE-Namen. ► Die Funktion open() gibt den Erfolg zurück: 1->ok, leer ->Fehler beim Öffnen der Datei. ► Nach Gebrauch wird die Datei mit close() geschlossen. |
$inpath = 'c:/test/test.txt';
# $inpath = "c:\\test\\test.txt";
print "Text-Datei $inpath:\n\n";
# open
$ok = open(READ1,$inpath);
print "open = $ok\n";if($ok) {
$i = 1;
}# Datei lesen
while ($line=<READ1>){
print "($i) $line";
}
$i++; print "\n"; close READ1;
|
|
Im Beispiel rechts oben wird die Datei in der while-Schleife
zeilenweise gelesen. <READ1> bezeichnet den Datenstrom,
liest bei jeder Verwendung eine Zeile und beendet die Schleife am Ende der Datei (eof). Jede Zeile wird einzeln an die Variable $line übergeben. |
Innerhalb der Lese-Schleife kann der Inhalt verarbeitet werden, meistens mit Hilfe von → Regulären Ausdrücken. Die 'Verarbeitung' beschränkt sich hier auf das Nummerieren der Zeilen mit der Variablen $i |
Minimal-VarianteDie Perl-Variable $_ enthält stets das Ergebnis der letzten Zuweisung - in diesem Fall je eine Zeile der Datei. |
open(READ2,$inpath) or die 'Fehler';
while(<READ2>) {print $_ ;} close READ2;
|
StringKleine Text-Dateien lassen sich in eine einzige Variable packen und damit noch rascher verarbeiten (Slurping).► Perl weist allerdings im Normalfall nur den Text bis zum ersten Trennzeichen \n zu. ► Die Perl-Variable $/ steuert die Trennung, Standard ist $/="\n"; Sie können bei Bedarf andere Trennzeichen zuweisen, oder die Variable mit undef löschen, wie rechts gezeigt. ► Die Reichweite der Änderung sollte möglichst klein ausfallen, daher wird sie mit local auf den Block in {} beschränkt. |
open(READ3,$inpath) or die 'Fehler';
{
local $/ = undef;
}
$strvar = <READ3>; close READ3;
print "$strvar\n"; |
ArrayAlternativ können sie den gesamten Inhalt der Datei an ein Array (hier @content) übergeben.Diese Methode ist z.B. sinnvoll, wenn der Inhalt der Datei sortiert wird, wie im Beispiel rechts. Die einzelnen Elemente werden zeilenweise nach \n getrennt. Die Perl-Variable $/ steuert die Trennung. (siehe voriger Absatz 'String'). Je nach Datei kann die letzte Text-Zeile am Ende ein \n enthalten oder nicht. Ein fehlendes Zeilenende wird hier bei Bedarf mit \n ergänzt. ♦ Details zu Perl-Arrays. |
open(READ4,$inpath) or die 'Fehler';
# Datei lesen my(@content) = <READ4>;
close READ4;
# Datei verarbeiten
sort(@content);
foreach $line(@content) {
if(!($line =~ m/\n$/))
{$line.="\n";}
print $line;
}
|
HashDas Beispiel rechts analysiert alle Worte einer Datei. Perl wird häufig für die Erzeugung eines Index verwendet, der als Grundlage für Such-Funktionen dient.Für diese Aufgabe gibt es zahlreiche Möglichkeiten, eine anschauliche wird hier gezeigt: ► Die Text-Datei wird zeilenweise in die Variable $line gelesen. ► Jede Zeile $line wird an den Wort-Grenzen in ein Array @linar zerlegt. ► Alle Worte $wd des Arrays, die länger als 3 Zeichen sind, werden in Kleinbuchstaben umgewandelt und im Hash %idx registriert: Das betreffende Hash-Element wird mit dem Wert 1 neu erzeugt oder hochgezählt, falls es bereits existiert. ► Zuletzt wird der Index alfabetisch sortiert und angezeigt. ♦ Details zum Durchforsten eines ganzen → Datei-Baums mit Perl. ♦ Details zu Perl-Hashes. |
my(%idx);
my(@linar); open(READ5,$inpath) or die 'Fehler'; while ($line=<READ5>){ @linar = split(/\W/,$line);
foreach $wd(@linar) {
if(length($wd)>3)
{$idx{lc($wd)}++;}
}
close READ5;
@ikeys = sort(keys %idx);
print "Index:\n";foreach $wd(@ikeys) { print "$wd(".$idx{$wd}.")\n";
}
|
Sonderzeichen:Zur Ein- oder Ausgabe von nicht druckbaren Sonderzeichen wie z.B. 0x0D oder 0x0A (\r oder \n) sollte man die Datei → binär lesen bzw. → schreiben ! |
Das ist auch dann notwendig, wenn die Datei selbst eine reine Text-Datei ist. Man kann in Perl → Reguläre Ausdrücke auch auf binäre Strings (d.h. 'Sonderzeichen') anwenden. |
HTML-Quelltext:Beim Lesen von HTML-Quelltext treten HTML-Elemente (tags) auf, wie z.B. <html>, <head>, <body> usw.• Wenn derartige Texte auf einer Webseite ausgegeben werden, dann werden sie als das verwendet, was sie sind: HTML-Elemente. • Oft ist jedoch die Anzeige als Quelltext erwünscht: In diesem Fall müssen alle tags 'maskiert' werden, d.h. so codiert, dass der Quelltext auf der Webseite erscheint. Das wird mit Funktion encode_entities() aus dem Modul HTML ausgeführt. Rechts ein Beispiel. Damit wird z.B. jedes Zeichen < aus dem gelesenen Text als < ausgegeben und damit als HTML-Quelltext angezeigt. ♦ Details zur Codierung und Maskierung von 'HTML-Zeichen'. |
use HTML::Entities;
$ok = open(READ6,'test.htm'); while ($line=<READ6>){
$line = encode_entities($line);
}
print $line; close READ6;
|
Text-Dateien schreiben |
|
open()Die Syntax der open()-Anweisung ist identisch mit jener zum ↑ Lesen von Dateien.Allerdings muss zum Schreiben unbedingt der mode angegeben werden: ► write oder > erzeugt eine neue Datei oder löscht eine vorhandene gleichnamige ungefragt. ► append oder >> erzeugt eine neue Datei oder hängt den Ausgabe-Text an eine vorhandene Datei an. ► read oder < liest eine Datei (↑ Datei lesen) |
# Linux-Pfad:
$outpath1 = '/home/test/ausgabe.txt';print "Ausgabe an Datei $outpath1\n";
$ok = open(WRITE1, "> $outpath1");
print "open = $ok\n";if($ok) { # Datei schreiben
print WRITE1 "Hier ist Perl !\n";} close WRITE1;
|
appendIm append-mode wird der Ausgabe-Text an eine bestehende Datei angehängt. Wenn die Datei noch nicht existiert, wird sie neu erzeugt.So werden z.B. Log-Dateien zur Dokumentation von Ereignissen geführt. Im Beispiel rechts wird jener Zeitpunkt notiert, an welchem das Script aufgerufen wurde. ♦ Details zum Datum und Zeit' in Perl. |
use POSIX qw/strftime/;
open(APP2, ">> $outpath2");
$dt=strftime '%Y-%m-%d %H:%M:%S', localtime;print APP2 "$dt Ereignis-Meldung\n"; close APP2;
|
HTMLMit Perl lassen sich auch 'normale' statische Webseiten schreiben.► Bei jeder Anforderung der betreffenden Webseite prüft ein winziges (Perl)-Programm, wann die Webseite zuletzt erzeugt wurde. Wenn ihr Alter zulässig ist (z.B. innerhalb eines Tages), dann wird die vorhandene statische Webseite gesendet. ► Wenn die Webseite veraltet oder (noch) nicht vorhanden ist, dann wird sie durch das Perl-Script neu erzeugt., jedoch nicht nur an den Browser gesendet, sondern für zukünftige Anfragen am Webserver gespeichert. ► Das ist sinnvoll, wenn Webseiten zwar automatisch erzeugt werden sollen, sich jedoch nicht individuell bei jedem Aufruf ändern, sondern über einige Zeit (z.B. 1 Stunde oder länger) stabil bleiben. ► Mit dieser Technik lassen sich Webserver merkbar entlasten. ► Details zum Erstellen von Webseiten mit Perl. Das Beispiel rechts stellt vor, wie man multiline-strings vorteilhaft verwendet: Man gibt mit einer Text-Marke (hier HTML_Block) Anfang und Ende des Strings an und kann in einem Zug beliebig viele (gleichbleibende) Zeilen schreiben. ► 'Voll'-dynamische Webseiten werden als → CGI-Scripts programmiert. |
$outpath3 = 'c:/myweb/test.htm';
open(WRITE3, "> $outpath3"); print WRITE3 <<'HTML_Block'; <html> <head> <title>Statische Webseite</title> <head> <body> Eine statische Webseite
</body></html> HTML_Block close WRITE3; |
copyEine Kombination von Lesen und Schreiben zeigt dieses Beispiel:Zunächst wird Datei $inpath5 zum Lesen geöffnet. Ihr Inhalt soll in die beiden anderen Dateien kopiert werden. Wenn eine der Dateien $outpath5 oder $outpath6 noch nicht existiert, wird sie neu erzeugt. In der Arbeits-Schleife wird $outpath5 mit dem Inhalt des Datenstroms <READ5> überschrieben. Der Inhalt von $outpath6 bleibt dagegen erhalten und wird (am Ende) mit <READ5> ergänzt. Eine einfache Kopie kann man auch einfacher herstellen, aber: • Innerhalb der Schleife haben sie Gelegenheit zur Verarbeitung der Inhalte, z.B. durch verschiedene Filter. Kombinationen von Lesen und Schreiben können sie u.a. dazu verwenden, um Dateien aus verschiedenen 'Bausteinen' zu erstellen, ähnlich wie die include-Anweisung von → PHP. |
# Lesen
open(READ5,$inpath5) or die 'Fehler';
# Überschreiben
open(WRITE5,"> $outpath5");
# Anhängen
open(APP6,">> $outpath6");
# Arbeits-Schleife
while ($line=<READ5>){
print $line;
}
print WRITE5 $line;
print APP6 $line;
# Abschluss
print "\n";print WRITE5 "\n"; print APP6 "\n"; close READ5; close WRITE5; close APP6; |
Standard-Kanäle |
|
| Die 3 Standard-Kanäle mit den Namen STDIN, STDOUT, STDERR sind ohne weitere Maßnahmen in jedem Programm geöffnet. |
STDIN ↔ Eingabe über Tastatur STDOUT ↔ Ausgabe im Konsolen-Fenster STDERR ↔ Ausgabe der Fehler-Meldungen (normalerweise ebenfalls im Konsolen-Fenster) |
Lesen von STDINDas Beispiel liest 1 Zeile vom Kanal STDIN - In Konsolen-Programmen von der Tastatur.Danach wird mit einem → Regulären Ausdruck das nachfolgende \n Newline-Zeichen entfernt, und der erhaltene Text ausgegeben - Ohne weitere Angaben verwendet print den Kanal STDOUT, d.h. das Konsolen-Fenster. |
print "Eingabe: "; # Aufforderung
$txt = <STDIN>; $txt=~s/\n$//; print "Text = $txt\n"; |
|
Das gleiche Beispiel in einer anderen Version und mit Verzicht auf den
Aufforderungs-Text. Der Kanal <STDIN> wird auch durch <> bezeichnet, die Entfernung von Newline-Zeichen erfolgt mit Funktion chop() oder chomp() |
$txt = <>;
chomp($txt); print "Text = $txt\n" |
| Das gleiche Beispiel in einer kompakten Variante. |
chomp($txt=<>);
print "Text = $txt\n"; |
Schreiben auf STDOUTDie beiden Zeilen des Beispiels sind äquivalent: Die Anweisung print (ohne File-Handle) arbeitet identisch wie mit Angabe von STDOUT |
print "abc\n";
print STDOUT "abc\n"; |
UmleitungGelegentlich ist es notwendig oder praktisch, einen I/O-Kanal an ein anderes Ziel zu leiten. Meist werden in diesem Fall die Standard-Kanäle STDIN, STDOUT temporär umgeleitet und danach wiederhergestellt.♦ Details zur Umleitung im ↓ nächsten Kapitel |
AbleitungWenn eine Ausgabe unerwünscht ist, jedoch aus irgendwelchen Gründen nicht abgeschaltet werden kann, dann leitet man den betreffenden Kanal zumindest temporär 'ins Leere'.♦ Details zur Ableitung im ↓ nächsten Kapitel |
WebserverWenn Perl für Webserver-Hilfsprogramme (CGI-Programme) verwendet wird, dann sind die Standard-Kanäle am Webserver orientiert und nicht am PC der/des (entfernten) Web-BesucherIn !Ein Browser-Programm wird nicht über die Tastatur bedient und verfügt auch über keine Text-Konsole zur Ausgabe. |
Für Webserver-Programme gilt: STDIN ↔ Eingabe-Kanal vom Webserver STDOUT ↔ Ausgabe-Strom an den Webserver = normalerweise HTML-Quelltext. STDERR ↔ Ausgabe an die Log-Datei des Webservers. |
|
Die Standard-Kanäle sind für Webserver-Programme normalerweise nicht zur
Kommunikation mit den AnwenderInnen nutzbar ! Auf Webseiten erfolgt die Weitergabe von User-Wünschen und -Daten meist über HTML-Formulare <form> und ihre Auswertung durch Webserver-Programme (z.B. in Perl , PHP, Python, ...). |
Eine selten genutzte Ausnahme ist die Übergabe von Argumenten mit der POST-Methode.
Nur in diesem Fall werden User-Daten im STDIN-Kanal an das Programm übergeben. Allerdings verwendet man auch in diesem Fall die viel besser geeigneten Methoden des Perl-Moduls CGI. |
|