in reply to Multiple identical keys in a hash.

I'm not sure I understood what the problem is, but can't you simply test on the keys with the same varname? i.e.:
if (defined $hash{$key}{$key}) { # do your thing }
Would that work? I used defined in this case because the value might be null, and that's not really what you're testing for, is it? You might still have the two levels assigned even if they do have a null value.

Spank me if I'm wrong...

#!/home/bbq/bin/perl
# Trust no1!

Replies are listed 'Best First'.
RE: Re: Multiple identical keys in a hash.
by ChuckularOne (Prior) on Apr 24, 2000 at 17:33 UTC
    My data is similar to:

    File 1

    dn=machinename
    config=2000
    speed=19200
    setting=value1
    setting=value2
    setting=value3

    File 2

    dn=machinename2
    config=2020
    speed=9600
    setting=value1
    setting=value2
    setting=value3


    I need for all occurances of setting to end up in the hash for file one, and then compare the contents of file two and output the differences.
      You could put all the values in array references indexed by your two-level hash. Something like this:
      foreach $f (@files) { open FILE, $f or die "Error: $!"; while(<FILE>) { chomp; my ($k,$v)=split("=",$_,2); # Assume dn= comes before other lines $level1=$k, next if $k eq "dn"; unless ($level1) { die "Need to get dn= line first\n"; } push @{$hash{$level1}{$k}}, $v; } close FILE; }
      Then you will have something like this:
      $hash{machinename}{config}=["2000"] $hash{machinename}{speed}=["19200"] $hash{machinename}{setting}=["value1", "value2", "value3"] $hash{machinename2}{config}=["2020"] etc.
      And then do comparisons or anything else you need. See chapter 4 of The Perl Cookbook for examples of how to do fancy array operations, including comparisons.
      If the machines have different names (assuming a normal network :o)), don't you just need to do this? (continued from ZZamboni's code)
      foreach $f (@files) { open FILE, $f or die "Error: $!"; while(<FILE>) { chomp; my ($k,$v)=split("=",$_,2); # Assume dn= comes before other lines if ($k eq "dn") { push(@machines,$k); $machine = $k; } else { push(@{$machine}{$k},$v); } } close FILE; }
      In this case you would end up with almost the same effect:
      @machines = ('machinename','machinename2'); ${'machinename'}{'config'} = 2000; ${'machinename'}{'speed'} = 19600; ${'machinename'}{'setting'} = value1, value2, value3; ${'machinename2'}{'config'} = 2020; ${'machinename2'}{'speed'} = 19600; ${'machinename2'}{'setting'} = value1, value2, value3; etc...
      Points being:
      1. do you have to name a hash?
      2. is it better to have @machines?

      I'm starting to wonder about this too...
RE: Re: Multiple identical keys in a hash.
by ChuckularOne (Prior) on Apr 24, 2000 at 17:46 UTC
    I forgot to say, the value of dn will be the $level1 key and all of the other name=value pairs will be $level2 key = value.

    Your humble servant,
    -Chuck
      So do you want a entry like:
      dn=machinename1
      name=value
      
      to yield:
      $hash{"machinename1"}{"name"}="value";
      
      or
      $hash{"machinename1"}{"name=value"}=1;
      
      in case 1 you should save the different values for name in an array. something like this should work
      foreach(@files){
          my $dn = "";
          open FILE, "$_" or die "error opening $_: ".$!;
          foreach(<FILE>){
      	chomp;
              $dn = $1 if(/dn=(.*)/);
              push @{$hash{$dn}{$1}}, $2 if(/(^=*)=(.*)/ && $dn ne "");
          }
          close FILE;
      }
      
      if it is case2, I don't know why you would need to add the same line more than once. if you need the number of occurances try :
       
      foreach(<FILE>){
          chomp;
          $dn = $1 if(/dn=(.*)/);
          $hash{$dn}{$_}++ if(/=)/ && $dn ne ""); 
      }
      
      for the inner loop. or use an array for the "name=value" entries:
      foreach(<FILE>){
          chomp;
          $dn = $1 if(/dn=(.*)/);
          push @{$hash{$dn}}, $_ if(/=/ && $dn ne "");
      }
      
      hope that helps.