birgit: In Hash zwei Arrays einfügen u Ausgabe tätigen

Halloo
ich habe ein Programm erstellt welches mir von zwei Directories bestimmte Files selektiert. Es werden hier dann zb. ein File aus Dir1 mit dem gleichen File aus Dir2 verglichen. Gibt es Werte die nicht übereinstimmen, werden diese in eine Txt-Datei übertragen.

Nun möchte ich aber, dass pro Datei mehr als ein Fehlerwert angezeigt wird.
Denn momentan schauts nur so aus.

Dir 1
hello.spi => 234
test.spi => 112

Dir 1
hello.spi => 235
test.spi => 111

Habs hierbei mal mit einem Hash probiert. Dh. die Filenamen (hello.spi) und die Werte (234) werden eingelesen.

nun gibt es aber zb. in der Datei test.spi einen weiteren Fehler, der wird jedoch nicht angzeigt. Die Ausgabe sollte wie folgt ausschaun:
test.spi => 111, 123

Ich wollte nun probieren die Werte als ein Array in den Hash einzulesen.
Aber hier komm ich einfach nicht weiter...

Viell. kann mir jemand behilflich sein, wär euch soooo dankbar!!!

  
my $sel_end="spi";  
  
my $dir = "@ARGV[0]";  
my @content0;  
my @liste_0;  
  
  
my $dir1 = "@ARGV[1]";  
my @content1;  
my @liste_1;  
  
my %HASH;  
  
opendir(DIR, "@ARGV[0]");  
opendir(DIR1, "@ARGV[1]");  
  
my @files0=readdir(DIR);  
my @files1=readdir(DIR1);  
  
  
foreach my $entry(@files0)  
{  # nach und nach die Einträge im Verzeichnis holen  
    my $path = "$dir/$entry";  
   # print "Dateipfad: $path\n";  
 if(-f $path)  
 {  
#  print "ARRAY: @files0\n";  
  
# Danach kommt ein split mit einem Punkt. Die Dateiendung ist der letzte Wert  
# des split (-1 ist ja immer der letzte Wert eines Arrays, also alles, was  
# hinter dem letzten . steht).  
  
  my $end=(split(/\./,$entry))[-1];  
  if($end eq $sel_end)  
  {  
#    print "Only $sel_end Files: $entry \n";  
  
   open(FILE,"<$dir/$entry")or die "file not found\n";  
   my @lines= <FILE>;  
    close (FILE);  
    push @content0, @lines;  
    delete $content0[0,1];  
  
    push @liste_0, $entry;  
  
    #print "LISTE0: @content0";  
#    print "liste0: @liste_0\n";  
  
  
    foreach my $entry1(@files1)  
    #while ($entry1 = readdir(DIR1))  
    {  # nach und nach die Einträge im Verzeichnis holen  
  
        my $path1 = "$dir1/$entry1";  
     if(-f $path1)  
     {  
     my $end1=(split(/\./,$entry1))[-1];  
      if($end1 eq $sel_end)  
      {  
       #print "ENTRY1: $entry1\n";  
  
       #print "Only $sel_end Files11: $entry1 \n";  
             #print "ARRAY11: $entry1\n";  
                   if ($entry ne $entry1)  
                   {  
                   next;  
                   }else  
                   # if ($entry eq $entry1)  
                   {  
#            print "ENTRY: $entry\n";  
#                   print "ENTRY1: $entry1\n";  
  
           open(FILE1,"<$dir1/$entry1")or die "file not found\n";  
           my @lines1= <FILE1>;  
           #my @content1;  
           close (FILE1);  
           push @content1, @lines1; # Array @content1 beinhaltet den Inhalt der Files, die verglichen werden sollen  
           delete $content1[0,1];  # Die ersten 2 Elemente des Arrays @content1 werden entfernt, da diese nur Kommentare sind  
           #print "LISTE1: @content1";  
  
           push @liste_1, $entry1;  
  
           print "ENTRY: $entry1\n";  
  
          }  
      }  
     }  
  
    }  
         my @content_0_1 = @content0;  # Array 1 minus Array 2;  
  
         for my $element (@content1) {  # Elemente des Arrays @liste_1  
                for my $index (0..$#content_0_1) { # Schleife über alle Indexe (Elemente) des Array liste_0_1 (=@liste_0)  
                    if ($element eq $content_0_1[$index]) { # Wenn ein Eintrag aus @liste_1 gleich dem Eintrag aus @liste_0 ($liste_0_1[$index] ist zB. text.txt) ist  
                        splice @content_0_1, $index, 1;  # splice (1. Name d. Arrays, 2. Indexnummer des Elements, ab dem gelöscht werden soll., Anzahl der zu löschenden Elemente)  
                        #last;        # Mit dem Befehl last kann die Schleife abgebrochen werden, wenn eine bestimmte Bedingung erfüllt ist  
                     ;  
  
                    }  
                }  
            }  
  
  
         my @content_1_0 = @content1;  # Array 2 minus Array 1;  
  
            for my $element (@content0) {  
                for my $index (0..$#content_1_0) {  
                    if ($element eq $content_1_0[$index]) {  
                        splice @content_1_0, $index, 1;  
                        #last;  
                    }  
                }  
            }  
  
  
            my %hash1;  
            my %hash2;  
  
          for my $i (0..$#liste_0)  
          {  
          $hash1{$liste_0[$i]}=$content_0_1[$i];  
            print $hash1;  
         }  
  
  
         for my $i (0..$#liste_1)  
         {  
          $hash2{$liste_1[$i]}=$content_1_0[$i];  
         }  
  
            open(DIFF,">diff_content.txt") || die("Can't open file\n");  
          print DIFF  "@ARGV[0]:\n";  
         print DIFF "$_ => $hash1{$_}" for keys %hash1;  
         print DIFF  "\n";  
         print DIFF  "\n";  
  
         print DIFF  "@ARGV[1]:\n";  
         print DIFF "$_ => $hash2{$_}" for keys %hash2;  
         print DIFF  "\n";  
 }  
 }  
 close(DIFF);  
  
  
}  
  
closedir(DIR1);  
closedir(DIR);  
  
  

  1. Hallo birgit!

    nun gibt es aber zb. in der Datei test.spi einen weiteren Fehler, der wird jedoch nicht angzeigt. Die Ausgabe sollte wie folgt ausschaun:
    test.spi => 111, 123

    Ich habe mir den Rest Deines Codes nicht angeschaut, aber ein HoA (Hash of Arrays) erhälst Du mit Dieser Notation:

    my %hash = (  
                 schluessel1 => ["wert0", "wert1"],  
                 schluessel2 => ["value0", "value1", "value2"],  
                 ...  
                );
    

    An die Werte der anonymen Arrays kommst du mit:

    $hash{'schluessel2'}[1]  # value1

    http://perldoc.perl.org/perldsc.html#HASHES-OF-ARRAYS

    Viele Grüße aus Frankfurt/Main,
    Patrick

    --

    _ - jenseits vom delirium - _
    [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
    Nichts ist unmöglich? Doch!
    Heute schon gegökt?
    All'alba vincerò!
    1. Hi..
      danke für deinen Tipp..
      hab mir die seite auch schon vorher angeschaut.

      doch mein problem ist, wie verbinde ich dann den Dateinamen mit den jeweiligen werten.

      Die Dateinamen sind meine keys und die Werte - die Values.. diese sollen in einem Array stehen.
      Doch ich hab keinen schimmer wie die richtigen werte beim richtigen dateinamen angezeigt werden solln :-(((
      heeeelp :-(

      Liebe Grüsse

      1. Hallo birgit!

        Es ist ziemlich mühselig, Dein Code zu verstehen... Vielleicht hilft Dir dieser Thread weiter, es geht um ein ähnliches Problem (Dateiinhalt zweier Dateien vergleichen):

        http://forum.de.selfhtml.org/archiv/2006/1/t121687/#m782447

        Doch ich hab keinen schimmer wie die richtigen werte beim richtigen dateinamen angezeigt werden solln :-(((

        Wie ermittelst Du, was die »richtigen« Werte sein sollen? Ich habe Dein Ausgangsposting so verstanden, dass Du nur in deine DIFF-Datei die Werte notieren willst, die differieren, bzw. wenn, dann in der Form: in dir1/datei.spi sieht es so aus, in der dir2/datei.spi sieht es dagegen so aus? Wenn Du die Werte allerdings schon erkennen kannst, dann kannst Du sie ja in einem HoA notieren oder was immer damit anstellen, wo ist also genau das Problem? Wie sehen die Dateien aus, welche Werte sollen verglichen werten?

        Viele Grüße aus Frankfurt/Main,
        Patrick

        --

        _ - jenseits vom delirium - _
        [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
        Nichts ist unmöglich? Doch!
        Heute schon gegökt?
        All'alba vincerò!
        1. Hi..

          Wie ermittelst Du, was die »richtigen« Werte sein sollen? Ich habe Dein Ausgangsposting so verstanden, dass Du nur in deine DIFF-Datei die Werte notieren willst, die differieren, bzw. wenn, dann in der Form: in dir1/datei.spi sieht es so aus, in der dir2/datei.spi sieht es dagegen so aus?

          ja genau, eigentlich sollen diese Werte nur miteinander verglichen werden.  und wenn die Werte nicht übereinstimmen sollen sie ausgegeben werden.

          Wenn Du die Werte allerdings schon erkennen kannst, dann kannst Du sie ja in einem HoA notieren oder was immer damit anstellen, wo ist also genau das Problem? Wie sehen die Dateien aus, welche Werte sollen verglichen werten?

          Diese Werte schaun ca. so aus: K1_2 L1 L2 6.469656e-003 (dh. eine Zeile)
          wie definiere ich das als code genau, dass der filename der key ist und die befinden sich in einem array?
          und dann gib ich jeweils den filenamen und die werte dazu aus.. mach noch nit wirklich lange perl deshalb tu ich mir hier so schwer :-((

          lg

          1. leider hab ich nen tippfehler
            meinte ...

            wie definiere ich das als code genau, dass der filename der key ist und die dazugehörigen werte befinden sich in einem array?

            1. Hallo birgit!

              Einfaches Beispiel:

              Datei 1.txt:
              item1=122
              item2=344
              item3=556

              Datei 2.txt:
              item1=123
              item2=343
              item3=556

              --------------

              use strict;  
                
              my $file1 = "1.txt";  
              my $file2 = "2.txt";  
                
              open (FILE_1, $file1) or die $!;  
              my @FILE_1 = <FILE_1>;  
              close FILE_1;  
                
              open (FILE_2, $file2) or die $!;  
              my @FILE_2 = <FILE_2>;  
              close FILE_2;  
                
              my %compare_hash = ();  
              my @diff1;  
              my @diff2;  
              for my $i ( 0..2 ) {  
                chomp $FILE_1[$i];  
                chomp $FILE_2[$i];  
                if($FILE_1[$i] ne $FILE_2[$i]) { push (@diff1,$FILE_1[$i]);  
                                                 push (@diff2,$FILE_2[$i]);  
                                                 $compare_hash{$file1} = \@diff1;  
                                                 $compare_hash{$file2} = \@diff2 }  
              }  
              print "Wo unterscheiden sich die Dateien: \n";  
              for (keys %compare_hash) { print "$_ = ";  
                                         {local $, = ", "; print @{$compare_hash{$_}}; }  
                                         print "\n"; }
              

              --------------

              Ausgabe:
              Wo unterscheiden sich die Dateien:
              1.txt = item1=122, item2=344
              2.txt = item1=123, item2=343

              Hinweis: Quirk&Dirty und sicher verbesserungswürdig. Ich muss jetzt weg und könnte evtl. Frage erst heute abend beantworten. Aber es sind noch andere hier ;)

              Viele Grüße aus Frankfurt/Main,
              Patrick

              --

              _ - jenseits vom delirium - _
              [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
              Nichts ist unmöglich? Doch!
              Heute schon gegökt?
              All'alba vincerò!
            2. wie definiere ich das als code genau, dass der filename der key ist und die dazugehörigen werte befinden sich in einem array?

              Indem Du die Dateien zeilenweise vergleichst, das allseits beliebte Tie::File sollte helfen:

              use Tie::File;  
                
              my $file1 = 'hier.txt';  
              my $file2 = 'dort.txt';  
                
              tie my @lines1, 'Tie::File', $file1 or die "Couldn't tie $file1: $!";  
              tie my @lines2, 'Tie::File', $file2 or die "Couldn't tie $file2: $!";  
                
              my %diff;  
                
              # wir setzen voraus, dass beide  
              # Dateien gleich viele Zeilen haben  
              for(0..$#lines1) {  
                if($lines1[$_] ne $lines2[$_]) {  
                  $diff[$_] = { $file1 => $lines1[$_],  
                                $file2 => $lines2[$_]  
                              };  
                }  
              }  
                
              untie @lines1;  
              untie @lines2;
              

              Der Hash ist dann so aufgebaut:

              {  
                ZeileNr_x => {  
                               'hier.txt' => 'Inhalt der Zeile',  
                               'dort.txt' => 'Anderer Inhalt'  
                             },  
                ZeileNr_y => {  
                               'hier.txt' => 'Inhalt der Zeile',  
                               'dort.txt' => 'Anderer Inhalt'  
                             },  
                # usw. usf.  
              }
              

              Jede andere Struktur wäre auch möglich, wie Du das umsetzt, lies bitte in perldsc nach.

              Siechfred

              --
              Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!
              1. Hallo Siechfred!

                Ach Siechfred, woher ahnte ich bei meiner letzten Antwort, dass sich die OP nicht mehr melden würde... Aber wenn ich darf, nur für's Archiv:

                $diff[$_] = { $file1 => $lines1[$_],
                                  $file2 => $lines2[$_]
                                };

                $diff{$_} ...

                BTW1: Ich habe drei Monate nicht geperlt, und ich habe den Eindruck, ich kann nichts mehr (teilweise noch nicht mal eigenen Code verstehen, wo ich länger dran saß)

                BTW2: Hat das einen besonderen Grund, dass in letzter Zeit öfters Tie::File empfohlen wird? OK, das Modul gehört zur Core. Ansonsten kennst Du meine Einstellung, dass ich grundsätzlich skeptisch gegenüber Modul-Empfehlungen für Anfänger bin, die sich bei einem Mietspace nicht »einfach so« installieren (bzw. kopieren) lassen (wie alle C-implementierte Module) ;)

                Viele Grüße aus Frankfurt/Main,
                Patrick

                --

                _ - jenseits vom delirium - _
                [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
                Nichts ist unmöglich? Doch!
                Heute schon gegökt?
                All'alba vincerò!
                1. $diff[$_] = { $file1 => $lines1[$_],
                                    $file2 => $lines2[$_]
                                  };
                  $diff{$_} ...

                  Natürlich. Danke für die Korrektur.

                  BTW2: Hat das einen besonderen Grund, dass in letzter Zeit öfters Tie::File empfohlen wird?

                  Es ist schnell und performant, gerade bei großen Files. Zumindest ist das meine Erfahrung.

                  Siechfred

                  --
                  Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!
                2. BTW2: Hat das einen besonderen Grund, dass in letzter Zeit öfters Tie::File empfohlen wird? OK, das Modul gehört zur Core. Ansonsten kennst Du meine Einstellung, dass ich grundsätzlich skeptisch gegenüber Modul-Empfehlungen für Anfänger bin, die sich bei einem Mietspace nicht »einfach so« installieren (bzw. kopieren) lassen (wie alle C-implementierte Module) ;)

                  Man kann aber durchaus mal einfach so den Vermieter fragen, zumindest meiner war da bisher immer sehr kooperativ. Zu Perl gehören die CPAN Module dazu ohne wäre es nur das halbe Produkt, was der hoster anbietet.

                  Struppi.

      2. doch mein problem ist, wie verbinde ich dann den Dateinamen mit den jeweiligen werten.

        Den Link zu perldsc hast Du jetzt schon zweimal bekommen, was verstehst Du genau nicht?

        Siechfred

        --
        Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!
  2. ich habe ein Programm erstellt welches mir von zwei Directories bestimmte Files selektiert. Es werden hier dann zb. ein File aus Dir1 mit dem gleichen File aus Dir2 verglichen. Gibt es Werte die nicht übereinstimmen, werden diese in eine Txt-Datei übertragen.

    Du vergleichst gleiche Dateien zeilenweise? Was soll dann in welcher Form in die Ergebnisdatei eingetragen werden? Dein Code sieht m.E. ziemlich unübersichtlich aus. Ansonsten gibt's ein CPAN-Modul File::DirCompare, das Dir den Vergleich abnimmt.

    Letztlich musst Du dann nur noch die Files vergleichen. Eine Hash-Struktur könnte dann so aussehen:

    {  
      'some_file.spi' => [ 1, 34, 1003 ],  
      'another_file.spi' => [ 23, 24 ]  
    }
    

    Siehe hierzu perldsc: Hashes od Arrays.

    Siechfred

    --
    Obacht, hinter jedem noch so kleinen Busch könnte ein Indianer sitzen!