Zum Inhalt springen

PERL 5.8 _ Bestimmte Werte aus einem Hash sortieren und in ein neuen Hash schreiben


Empfohlene Beiträge

Guten Morgen zusammen,

ich habe ein Aufgabe in PERL bekommen, ich arbeite auf einem uralten UNIX AIX System und kann nur auf eine geringe Anzahl von PERL-Modulen zugreifen da durch Compliance-Regeln der IT-Sec echt ängstlich ist.

 

Aber jetzt zum Topic:

Ich habe das Problem, dass ich in UNIX/Linux Case Sensitive Dateinamen habe, d.h. es kann vorkommen, dass eine Datei mit  "gleichem Namen" 2x auftaucht, ich aber die Jüngste brauche und ich kann in meiner Subroutine die Bedingung dafür nicht ordentlich formulieren, da ich schon Knoten im Hirn habe und für mich PERL echtes Neuland ist.

Könnt Ihr mir da irgendwie helfen? 

 

#!/usr/bin/perl -w
use strict;
use warnings;

use File::Stat;
use File::Copy;

use POSIX;
use Data::Dumper;

# Dieses Skript MUSS im Verzeichnis der gesuchten Daten liegen, da sonst der 
# LastModifikation-Stamp nicht eingelesen wird

my $directory = '/home/wizzard/caseSens/xml';
my $bak_directory = '/home/wizzard/caseSens/OLD';
my $filename;
my $lastmod_on_file;
my $key;

my %filenames_and_timestamps;
my %temphash;
my %hash_ref;

opendir DIR_HANDLE, $directory || die "Can not open directory $directory: $!"; 

    while ( $filename = readdir DIR_HANDLE ) {
      
        next unless $filename =~ /\.xml$/;      # Alle XML Dateien werden gelesen        
                                          
        next if $filename =~ /^\./;             # "Punkt"-Dateien überspringen
        
        # $filename = "$directory/$filename";   # Verzeichnis hinzufügen

        #LastModifed Stamp wird ermittelt
        my ($dev, $ino, $mode, $nlink, 
            $uid, $gid, $rdev, $size, 
            $atime, $mtime, $ctime, 
            $blksize, $blocks) = stat ($filename);

        $lastmod_on_file = $mtime;
        
        # Die Hashmap wird mit allen Bedingungen befüllt
        $filenames_and_timestamps{ $filename } = $lastmod_on_file; 
        
    }
    
    &filename_and_lastmod_sort();
    
closedir DIR_HANDLE;




#########################################################################
#                       PROZESS LOGIK
#########################################################################
#
#   Alle Dateinamen stehen als Key in der Hash 
#    das Last Modified Date ist die Value
#
#    Der Hash steht nur noch als Referenz zur Verfügung, und zwar wie folgt
#
#
#    Doppelte Dateinamen finden in dem ein PatternMatching von DateiEbene
#    auf das Hash zeig, und anhand des Matching den Key findet.
#
#   Allerdings kann es durchaus sein, dass durch CaseSensible ZWEI Keys gefunden
#     werden die sich nur durch Groß- und Kleinschreibung unterscheden. 
#    Diese werden anhand der Value (LastModifed Date) sortiert und 
#    das Jüngste/Neueste, unabhängig von Groß- und Kleinschreibung, wird dann behalten.

#
#     Ältere Daten werden verschoben in OLD
#    
#
#    Hash wird Sortiert nach Key im UPPERCASE und dann nach Timestamp
#    Die jeweils älteste Datei wird verschoben in ein "OLD" Verzeichnis.
#    
#     Daten die bei denen es keine neuere Version gibt in "alter Schreibeweise ACECadPart-xxxxxxxx" werden
#     in UPPERCASE umbenannt
#    


sub filename_and_lastmod_sort {
#    sortiert alphanummerisch nach dem Key 
#    UND bei Gleichheit nummerisch absteigend nach der Value.
#

    print "\n\nAlle Datein werden nach Filename sortiert\nund absteigend nach Datum\n";
    
    foreach my $key ( sort {  uc($a) cmp  uc($b) || $filenames_and_timestamps{ $b } <=> $filenames_and_timestamps{ $a } } keys %filenames_and_timestamps) {
    
        # Ab hier soll ein weiteres Hash befüllt werden mit den jüngsten Daten

        printf "%-8s %s\n", $key, $filenames_and_timestamps{$key};    
        
        #&bereinigung($filenames_and_timestamps{$key});
        
    }    
    &bereinigung();
}

#
# Hier liegt für mich der Hund begraben, da ich die Syntaktische Bedingung in Perl nicht formulieren kann, ich nutze nur VIM und kann nicht wirklich #debuggen
#

sub bereinigung {

    if ( $filenames_and_timestamps{$key} <= ($b)  ) {
        
        print "hello world\n";
        
    }else{
        
        print "goobye\n";
        
    }
        
}

print "\nHash unberührt \n";
print Dumper(\%filenames_and_timestamps);

print "\nTempHash bereinigt \n";
print Dumper(\%temphash);

Das hier sind die Beispieldaten mit denen ich Arbeite :

Terminalausgabe:

Hash unberührt 
$VAR1 = {
          'ACECadPart-M00000000008R3.xml' => 1583240787,
          'ACECADPart-M00000000001R3.xml' => 1583240831,
          'ACECADPart-M00000000004R3.xml' => 1583240800,
          'ACECADPart-M00000000006R3.xml' => 1583741482,
          'ACECADPart-M00000000007R3.xml' => 1583240813,
          'ACECADPart-M00000000002R3.xml' => 1583240796,
          'ACECadPart-M00000000004R3.xml' => 1583742311,
          'ACECadPart-M00000000002R3.xml' => 1583240764,
          'ACECADPart-M00000000003R3.xml' => 1583240822,
          'ACECadPart-M00000000001R3.xml' => 1583240792,
          'ACECadPart-M00000000003R3.xml' => 1583240756,
          'ACECadPart-M00000000006R3.xml' => 1583240777,
          'ACECadPart-M00000000007R3.xml' => 1583240782,
          'ACECADPart-M00000000008R3.xml' => 1583240817,
          'ACECADPart-M00000000005R3.xml' => 1583240804,
          'ACECadPart-M00000000005R3.xml' => 1583240772
        };

 

Alle Datein werden nach Filename sortiert
und absteigend nach Datum
ACECADPart-M00000000001R3.xml 1583240831
ACECadPart-M00000000001R3.xml 1583240792
ACECADPart-M00000000002R3.xml 1583240796
ACECadPart-M00000000002R3.xml 1583240764
ACECADPart-M00000000003R3.xml 1583240822
ACECadPart-M00000000003R3.xml 1583240756
ACECadPart-M00000000004R3.xml 1583742311
ACECADPart-M00000000004R3.xml 1583240800
ACECADPart-M00000000005R3.xml 1583240804
ACECadPart-M00000000005R3.xml 1583240772
ACECADPart-M00000000006R3.xml 1583741482
ACECadPart-M00000000006R3.xml 1583240777
ACECADPart-M00000000007R3.xml 1583240813
ACECadPart-M00000000007R3.xml 1583240782
ACECADPart-M00000000008R3.xml 1583240817
ACECadPart-M00000000008R3.xml 1583240787

 

 

 

Bearbeitet von der.milchjieper
Detailänderung
Link zu diesem Kommentar
Auf anderen Seiten teilen

  • 2 Wochen später...

Moin,

keine Ahnung ob das noch relevant ist und mein PERL ist deutlich eingerostet, es gibt also vermutlich bessere Lösungen

Ich würde das auch andersrum angehen. Ich würde die Dateien zunächst "falsch" herum sortieren, so das die neueste Datei immer die letzte ist. Das Ergebnis schiebe ich erstmal in ein temporären Hash mit dem uppercase Filename als key.

$tmp{uc($key)} = [ $key, $filenames_and_timestamps{$key} ];

daraus bastel ich dann den temphash und sortiere bei bedarf nochmal in der richtigen Reihenfolge

foreach my $key (keys %tmp) {
        $temphash{$tmp{$key}[0]} = $tmp{$key}[1];
}

sicher nicht sonderlich effizient, aber das versteh ich auch in 6 Monaten noch ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...