Font
[thread]8280[/thread]

Dateien durchsuchen (war: Kann man das so machen1)



<< >> 6 entries, 1 page
rk-ger
 2006-08-29 00:53
#69331 #69331
User since
2006-08-07
45 articles
BenutzerIn
[default_avatar]
Hallo,

ich fange grade mit Perl an. Das folgende Programm funktioniert, aber ist der Stil auch OK? Wo habe ich zu kompliziert und umständlich gearbeitet? Jede konstruktive Kritik ist willkommen.

Die selbstgestellte Aufgabe war: in einem Verzeichnis liegen viele Dateien. Jede Datei mit einer bestimmten Endung und ohne '~' am Dateianfang soll geparst werden. Dabei soll jede Zeile darauf hin geprüft werden, ob ein bestimmter String enthalten ist. Wenn ja, dann Rückgabe der Nummer. Ansonsten einfach nur eine Meldung ausgeben.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use strict;
use warnings;
my $filename = ""; # für den dateinamen
my $startdir = "c:\\foo\\bar\\"; # in welchem dir geht es los?
my $NR_found; # für die NR
opendir(DIR, $startdir) or die "Verzeichnis kann nicht geöffnet werden: $!\n";
while (defined ($filename = readdir(DIR))) {
if (-f "${startdir}$filename" and $filename =~ /(^[^~].*\.txt)$/i) { # richtige art von datei?
# und dann zum lesen öffnen
open IN,"<${startdir}$filename" or die "Datei kann nicht geöffnet werden -> ${startdir}$filename : $!";
my @in = <IN>;
$NR_found = "0"; # variable zurücksetzen
foreach my $line (@in) { # jede datei zeilenweise durchgehen
if ($line =~ /(NR \d{7})/) { # was sinnvollen gefunden?
$NR_found = $1; # dann speichern
}
} # alle zeilen durch?
if ( not $NR_found eq "0") { # haben wir was?
print "mit NR ->$NR_found\n"; # dann drucken
}
else {
print "keine NR Nr.\n"; # oder fehlschlag melden
}
close (IN); # zumachen
}
}
closedir (DIR); # auch da zumachen


Gruß
Richard
lichtkind
 2006-08-29 00:58
#69332 #69332
User since
2004-03-22
5660 articles
ModeratorIn + EditorIn
[Homepage]
user image
naja im gropen schon ein paar leerzeilen hier und da etwas mehr einrückung vielleicht, auch deine klammerplatzierung ist nicht ganz einer der üblichen standarts. auch die kommentare würd ich mir eher fuer sachen aufheben die bei deri (wieder-) einarbeitung helfen koennten und weniger offensichtlich sind.
Wiki:Tutorien in der Wiki, mein zeug:
kephra, baumhaus, garten, gezwitscher

Es beginnt immer mit einer Entscheidung.
rk-ger
 2006-08-29 01:17
#69333 #69333
User since
2006-08-07
45 articles
BenutzerIn
[default_avatar]
Die Leerzeilen hatte ich extra rausgenommen, um das Codebeispiel kürzer zu halten. War vielleicht keine so gute Idee.

Aber vielen Dank für den Kommentar.

Gruß
Richard
Ronnie
 2006-08-29 01:57
#69334 #69334
User since
2003-08-14
2022 articles
BenutzerIn
[default_avatar]
Eine Alternative:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/perl

use strict;
use warnings;

my @files = grep { $_ !~ /^~/ } (<*.txt>);
my @matches;

foreach my $file (@files) {
open (my $fh, '<', $file) or die $!;
/(NR \d{7})/g and push @matches, $1 while (<$fh>);
close $fh or die $!;
}

print "@matches\n";
\n\n

<!--EDIT|Ronnie|1156802287-->
Dubu
 2006-08-29 22:18
#69335 #69335
User since
2003-08-04
2145 articles
ModeratorIn + EditorIn

user image
[quote=rk-ger,28.08.2006, 22:53]
Code: (dl )
1
2
use strict;
use warnings;
[/quote]

Sehr löblich.

Quote
Code: (dl )
my $startdir = "c:\\foo\\bar\\";            # in welchem dir geht es los?


Man kann unter DOS/Windows wie unter UNIX/Linux auch den Vorwärtsschrägstrich als Verzeichnistrenner benutzen, was meist etwas übersichtlicher ist.
Code: (dl )
my $startdir = 'C:/foo/bar/';


Quote
Code: (dl )
1
2
                                                # und dann zum lesen öffnen
     open IN,"<${startdir}$filename" or die "Datei kann nicht geöffnet werden -> ${startdir}$filename : $!";


Bei neueren Perl-Versionen wird die "3-Parameter-Form" von open() bevorzugt, weil sie sicherer ist.
Ich persönlich bevorzuge es auch, beim Zusammensetzen von Pfad und Dateinamen explizit einen Pfadtrenner zu setzen (dann kann man ihn beim Pfadnamen problemlos weglassen).
Code: (dl )
open (IN, '<', "$startdir/$filename") or die "...";



Quote
Code: (dl )
1
2
3
4
5
6
7
      my @in = <IN>;
     $NR_found = "0";                     # variable zurücksetzen
     foreach my $line (@in) {               # jede datei zeilenweise durchgehen
      if ($line =~ /(NR \d{7})/) {         # was sinnvollen gefunden?
         $NR_found = $1;                  # dann speichern
       }
     }                                 # alle zeilen durch?


Es ist ineffizient, erst die ganze Datei einzulesen und dann zeilenweise durchzugehen. Besser direkt zeilenweise einlesen und abarbeiten. Auch kann man die Schleife abbrechen, wenn ein Treffer gefunden wurde (außer, es können mehrere Treffer in der Datei vorkommen und du möchtest immer gerade den letzten haben).

Code: (dl )
1
2
3
4
5
6
7
$NR_found = "0";
while (my $line = <IN>) {
   if ($line =~ /(NR \d{7})/) {
       $NR_found = $1;               # Treffer speichern
       last;                         # Schleife abbrechen
   }
}


Quote
Code: (dl )
      if ( not $NR_found eq "0") {            # haben wir was?


Oder:
if ($NR_found ne "0") ...
rk-ger
 2006-08-31 22:12
#69336 #69336
User since
2006-08-07
45 articles
BenutzerIn
[default_avatar]
Super Antwort. Vielen Dank. Und wieder was gelernt...
<< >> 6 entries, 1 page



View all threads created 2006-08-29 00:53.