Perlkurs Dateiverarbeitung Dr. Deutsches Krebsforschungszentrum Gruppenleiter Bioinformatik
Umgang mit Dateien in Perl Dateitest- oder Prüfoperatoren um was für eine Art Datei handelt es sich? Durch Verzeichnisse gehen (alle) Dateien darin bearbeiten Dateien in Perl öffnen zum Lesen, Schreiben, Anhängen Eine Datei Zeile für Zeile durchgehen Ausgabe auf STDERR Formatierte Ausgabe Parameter übergeben Lesen von STDIN Dateien umbenennen und löschen Fehlerbehandlung
Dateitest-Operatoren -e File or directory name exists -f Entry is a plain file -d Entry is a directory -z File exists and has zero size (always false for directories) -s File or directory exists and has nonzero size (the value is the size in bytes) -r File or directory is readable by this (effective) user or group -w File or directory is writable by this (effective) user or group -x File or directory is executable by this (effective) user or group Quelle: http://www.devshed.com/c/a/perl/file-tests-in-perl/
Verzeichnisse durchgehen I my $dirtoget="/home/yourname/www/images/"; opendir (DIR, $dirtoget) die ("Cannot open directory $dirtoget\n"); my @thefiles = readdir (DIR); # store names of files in an array closedir (DIR); foreach my $file (@thefiles) unless ( ($file eq ".") ($file eq "..") ) # special Unix "files" print "$file is a real file\n";
Verzeichnisse durchgehen II if (-d $dirtoget) opendir (DIR, $dirtoget) die ("Cannot open directory $dirtoget\n"); foreach my $file (readdir DIR) # implicit array if (-f $dirtoget."/".$file) # need complete path to file print "$file is a real file\n"; else print "$dirtoget is not a directory (or does not exist)\n"; closedir DIR;
Im Programm eine Datei öffnen Zuweisung eines file handle und des Öffnungsmodus open (IN, "<".$datei); # zum Lesen open (IN, $datei); # zum Lesen, Kurzform open (OUT, ">$datei"); # zum (über)schreiben open (LOG, ">>".$datei); # zum Anhängen ACHTUNG: Wenn die Datei nicht im aktuellen Verzeichnis liegt (bzw. angelegt werden soll), muss die Variable mit dem Dateinamen den kompletten Pfad enthalten, z.b. $datei="/home/student/documents/myfile.txt";
Eine Datei einlesen #Prüfen, ob Datei zum Lesen geöffnet werden kann open (FH, $input) or die "Could not open $input: $\n"; ($ = Fehlermeldung, meist no such file or directory oder permission denied ) #Erste Zeile einlesen $line = <FH>; #Zeile für Zeile durchgehen und bearbeiten while (<FH>) # Kurzform von: while ($_ = <FH>) chomp; # mache etwas mit der Zeile, hier: my @spalten = split ("\t", $_); # den Zeilenumbruch entfernen, print $spalten[0]; ausgeben #Schließen close (FH); # in ein array umwandeln und den # ersten Eintrag des Arrays
In eine Datei schreiben #Prüfen, ob Datei angelegt werden kann open (OUT, '>'.$outfile) or die "Could not open $outfile for writing: $\n"; #Etwas zum Ausgeben konstruieren my @array = ("Zeile 1", "Zeile 2", "Zeile 3"); #Schreiben foreach my $line (@array) print OUT "$line\n"; #Schließen close OUT;
Ausgabemöglichkeiten print Kurzform von print STDOUT Kann in eine Datei umgeleitet werden: perl myprog.pl > ausgabe.txt print STDERR Bei Umleiten von STDOUT immer noch da Umleiten in eine Datei mit 2> Dies leitet auch Fehlermeldungen und Warnungen um print FH In eine Datei, die mit den file handle FH angesprochen wird
Formatierte Ausgabe I: printf $Pi = 3.1415126; printf ("%d", $Pi); # no decimal places #=> 3 printf ("%.3f", $Pi); # round number to 3 digits after decimal point #=> 3.142 $Cost = 499; printf "The cost is \$%6.2f\n", $Cost; #=> The cost is $499.00 \$, um $ als Zeichen auszugeben: escape \n für Zeilenumbruch
Formatierte Ausgabe II: sprintf #Gibt einen formatierten String zurück $rounded = sprintf("%.3f", $number); print $rounded; #ACHTUNG bei Runden auf Ganzzahl $rounded = sprintf ("%.0f\n", 0.5) => 0 $rounded = sprintf ("%.0f\n", 0.51) => 1 $rounded = sprintf ("%.0f\n", 3.5) => 4 # Korrekt Runden: foreach my $number (0.5, 0.51, 3.5) $rounded = int ($number+0.5); print "$rounded "; => 1 1 4
Kommandozeilenparameter Spezial-Array @ARGV Programmaufruf: script.pl arg1 arg2 In script.pl: if (@ARGV < 2) die "Das Programm $0 braucht Kommandozeilenparameter. Nämlich folgende: 1.... 2. \n"; my $arg1 = shift; # $ARGV[0] my $arg2 = shift; # $ARGV[1]
Beispiel #/usr/bin/perl use strict; use warnings; if (@ARGV < 2) # command line arguments given to the program die "USAGE of $0: 1.file to read 2. file to write\n"; my $input = shift; # get the path of the file to read from (given by first command line argument) open (FH, $input) or die "Could not open $input: $\n"; # open file for reading, give it a file handle my $outfile = shift; # get the path of the file to write to (given by second command line argument) open (OUT, '>'.$outfile) or die "Could not open $outfile for writing: $\n"; my $line = ""; # to store the lines my $counter = 0; # to count the lines while (<FH>) # read file line by line until the end. This is the short form of: while ($_ = <FH>) $counter++; $line = $_; # store the current line in a variable chomp $line; # remove the newline character print OUT "$line"; # output the line without newline character into a file print "$counter\n"; # output number on the screen, this can be redirected with > print STDERR "$_"; # print the original line (still with newline character) on STDERR, this can be redirected with 2> close (FH); # close the file close (OUT); print STDERR "There were $counter lines in $input\n"; exit;
Lesen von STDIN Programme, die Benutzereingaben erwarten Eingabewerte/ in Datei speichern, jede Eingabe in neue Zeile Diese Datei übermitteln mittels pipe cat myinput.txt I_read_from_stdin oder redirection I_read_from_stdin < myinput.txt Im Perl-Programm STDIN als Quelle definieren $input = <STDIN>; while (<STDIN>) Perl kann eine pipe wie eine Datei behandeln I_write_to_STDOUT perl meinskript.pl in meinskript.pl: my $infile = shift; open
Dateien umbenennen und löschen #Datei umbenennen my $oldfile = "test/file1.txt"; my $newname = "test/file2.txt"; rename ($oldfile, $newname); #Datei löschen my $filetodelete = "test/file1.txt"; unlink ($filetodelete); #Verbesserung: erst testen, ob die Datei existiert if (-f $filetodelete)...
Typische Fehler I open vergessen oder falsche Option readline() on unopened filehandle [FHName] at [Skriptname] line... print() on unopened filehandle [FHName] at [Skriptname] line... Vergessen von: $ No such class [Variablenname] at [Skriptname] line..., near "my [Variablenname]" ; Syntax error at [Skriptname] line..., near... my Can't modify constant item in... at [Skriptname] line..., near Bareword "[Variablenname]" not allowed while "strict subs" in use at [Skriptname] line... Missing right curly or square bracket at [Skriptname] line..., at end of line Syntax error at [Skriptname] line..., at EOF ) Syntax error at [Skriptname] line... near "
Typische Fehler II Vergessen von " Bareword found where operator expected at... (Might be a runaway multi-line "" string starting on line...) (Do you need to predeclare print?) Backslash found where operator expected... String found where operator expected... (Missing semicolon on previous line?) syntax error at... Can't find string terminator '"' anywhere before EOF at... Fence post error Zugriff auf nicht existierende Arrayelemente my @array = (1, 2); print $array[2], \n"; => Use of uninitialized value $array[2] in print at Tippfehler
Wiederholung: Hash #Leeren Hash erzeugen my %h = (); #Neues Schluessel/Wert Paar anlegen $h Fred ="Flintstone"; #Eintrage aus Hash loeschen delete $h Fred ; #Existenz eines Schlüssel/Wert Paars testen if (exists ($h Fred ))
Acknowledgements Barbara Hutter