Hi!
Tatsache ist, dass ich das Ganze erst in Bash / awk gemacht hab' und erst dann zu Perl umgeschwenkt bin, um 'ne befriedigendere Lösung zu erhalten. Hat nur leider nicht so geklappt, wie ich mir das gedacht hab'.
Außerdem zielte meine Frage auch eher auf allgemeine Gründe ab (wie z.B. ein Überlauf des Wertebereichs einer sein könnte) als auf konkrete Fehler im Quellcode. Nichtsdestotrotz hier der Perl-Code:
#!/usr/bin/perl
#######################
# Includes #
#######################
use English;
use HelpTools; #eigenes Modul
use strict;
no strict "refs";
use utf8;
#######################
# Deklarationsteil #
#######################
#Std.-Skalare
my $Source = "out.txt";
my $RegExSource = "prep.txt";
my $Dest = "summ.txt";
my $Diag = 0; # Diagnoseausgaben (0 = AUS, 1 = AN)
my $Errors = 0;
my $aktRegex = "";
my $aktZeile = "";
#Zähler
my $SizeHDD = 0;
my $SizeBand = 0;
my $countHDD = 0;
my $countBand = 0;
my $durchsuchte = 0;
#Arrays
my @Regexe;
#Hashes
my %count; #zählt für jeden Regex die Anzahl der gefundenen Zeilen => vielleicht finden wir dadurch raus, wo die Speicherdifferenzen herkommen
#######################
# Implementationsteil #
#######################
#Dateihandles oeffnen
sub openHandles(){
#Quelldatei öffnen
if (-e $Source){ #Falls Datei existiert
if (open (SOURCE_HANDLE, '<' , $Source)){print "Quelldatei \"$Source\" erfolgreich geoeffnet.\n" if ($Diag)} #falls das Öffnen klappt
else {die "Die Quelldatei \"$Source\" konnte nicht geoeffnet werden: $!.\n";} #sonst Fehler melden
}
else {print "Die Quelldatei \"$Source\" existiert nicht: $!.\n";} #sonst Fehler melden
#Quelle für Regular Expressions öffnen
if (-e $RegExSource){ #Falls Datei existiert
if (open (REGEX_HANDLE, '<' , $RegExSource)){print "Regex-Quelldatei \"$RegExSource\" erfolgreich geoeffnet.\n" if ($Diag)} #falls das Öffnen klappt
else {die "Die Regex-Quelldatei \"$RegExSource\" konnte nicht geoeffnet werden: $!.\n";} #sonst Fehler melden
}
else {print "Die Regex-Quelldatei \"$RegExSource\" existiert nicht: $!.\n";} #sonst Fehler melden
#Zieldatei öffnen
if (open (DEST_HANDLE, '>' , $Dest)){print "Zieldatei \"$Dest\" erfolgreich geoeffnet.\n" if ($Diag)} #falls das Öffnen klappt
else {die "Die Zieldatei \"$Dest\" konnte nicht geoeffnet werden: $!.\n";} #sonst Fehler melden
return 1;
}
#Dateihandles schliessen
sub closeHandles(){
#Dateihandles schließen
unless (close SOURCE_HANDLE) {die "Das Dateihandle zur Datei \"$Source\" konnte nicht geschlossen werden: $!.\n"; $Errors++;}
unless (close REGEX_HANDLE) {die "Das Dateihandle zur Datei \"$RegExSource\" konnte nicht geschlossen werden: $!.\n"; $Errors++;}
unless (close DEST_HANDLE) {die "Das Dateihandle zur Datei \"$Dest\" konnte nicht geschlossen werden: $!.\n"; $Errors++;}
if ((!$Errors) && ($Diag)){print "Alle Dateihandles erfolgreich geschlossen. Programm wird beendet.\n";}
return 1;
}
#Ergebnisse in die Ausgabedatei schreiben
sub Ausgabe(){
print DEST_HANDLE "$_[0]\t\t$countBand\t$SizeBand\t$countHDD\t$SizeHDD\n";
#print "$aktRegex\t$countHDD\t$SizeHDD\t$countBand\t$SizeBand\n";
return 1;
}
#alle RegExes aus Datei in ein Array übertragen
sub prepareRegex(){
#Regexe aus Datei lesen
while (<REGEX_HANDLE>){
chomp;
push (@Regexe, $_);
}
#Diagnoseausgabe
if ($Diag){
foreach my $Regex (@Regexe){
print DEST_HANDLE "REGEXE: " . $Regex . "\n";
}
print DEST_HANDLE "======================================================================================\n";
}
return 1;
}
&openHandles();
&prepareRegex();
print DEST_HANDLE "Ordnername\tAnzahlBand\tGroesseBand\tAnzahlPlatte\tGroessePlatte\n\n";
foreach my $Regex (@Regexe){
if ($Regex ne ""){
seek(SOURCE_HANDLE, 2, 0); #seek(DATEIHANDLE, Zeilennummer (ab 1 indiziert), Offset);
while (<SOURCE_HANDLE>){
#chomp;
#print "Zeile: " . $_ . "\n";
$aktZeile = $_;
#Beispielzeile: san-work-goobi-backup.dir 14 4032 2 2.72933e+09
#if ($aktZeile =~ m/$aktRegex/gi){
if ($aktZeile =~ m/$Regex\t/gi){
#$aktZeile =~ m/\t(\d+)/gi; #Spalte 1
$aktZeile =~ m/(\d+)\t(\d\.?\d+e\+\d{2}|\d+)\t(\d+)\t(\d\.?\d+e\+\d{2}|\d+)/gi;
$countHDD += $1;
$SizeHDD += $2;
$countBand += $3;
$SizeBand += $4;
$count{$Regex} += 1;
}
$durchsuchte++; # = Regexe * zu pruefende Zeilen
}
&Ausgabe($Regex);
#Zaehlvariablen fuer naechsten Unterordner zuruecksetzen
$SizeHDD = 0;
$SizeBand = 0;
$countHDD = 0;
$countBand = 0;
}
}
print DEST_HANDLE "Durchsuchte: $durchsuchte." if ($Diag);
while ( my ($k,$v) = each %count ) {
print "$k => $v\n";
}
&closeHandles();
Der AWK-Code sieht so aus:
BEGIN {
AnzB=0;
AnzP=0;
SizeB=0;
SizeP=0;
#OFMT="%.15g"; #Output Format
OFMT="%i"; #Output Format
}
AnzB+=$4;
AnzP+=$2;
SizeB+=($5); # kommt in Bytes aus der Datei
SizeP+=($3); # kommt in Bloecken zu je 1 kB aus der Datei
END {
print(Arg " " AnzB " " SizeB " " AnzP " " SizeP);
}
Die verwendeten Dateien. out.txt sieht auszugsweise so aus:
prep.txt sieht auszugsweise so aus:
So, ich hoffe, ich hab' erst mal nix vergessen. Vielen Dank übrigens für deine schnelle Antwort!
Bis bald,
DasFaultier
EDIT:
Hab' natürlich doch noch was vergessen. Erstens das Aussehen der summ.txt, die da entstehen soll:
und zweitens das Bash-Script:
#!/bin/bash
#Verwendung: "./summ.sh"
#WICHTIG: Da die Datei "sehrKurzeVerzeichnisliste.txt" ausgewertet wird, müssen Sie durch Aufruf des Programms "kompletteVerzeichnisListe.sh" sicherstellen, dass diese auch existiert.
sed "s/^-//gi" sehrKurzeVerzeichnisliste.txt | sed "s/\s/_/gi" > prep.txt
echo "Ordnername AnzahlBand GroesseBand AnzahlPlatte GroessePlatte";
echo;
for ELEMENT in `more prep.txt`; do
ELEMENT="$ELEMENT "; # Tabulator anfuegen, um nur Wurzelverzeichnisse zu triggern (alle Unterverzeichnisse bleiben unangetastet)
grep -e "${ELEMENT}" out.txt | gawk -v Arg="${ELEMENT}" -f ./summ.awk | grep -v "san-";
done
#rm prep.txt; #Kommentierung entfernen, um temporäre Datei "prep.txt" nach Ausführung des Scriptes zu löschen
Als kurze Erklärung vielleicht noch: out.txt ist das Ergebnis des ersten Zwischenschrittes der Berechnungen. Die Ergebnisse in dieser Datei sind verifiziert und richtig. Hier wird der verwendete Speicherplatz pro Unterverzeichnis aufaddiert. In prep.txt liegen verkürzte Pfade aller ähnlich klingenden Unterverzeichnisse. summ.txt enthält dann die Summe des Speicherplatzes aller ähnlich klingenden Unterverzeichnisse.