teamassociated has asked for the wisdom of the Perl Monks concerning the following question:

I am pretty sure my logic is working well, however not perfect. When I type in a fake non-existent wwn string it returns nothing in all cases. For example, 2009000g123456ff below is fake. Which is fine because I verify manually, but ideally I would like a "not found" warning and move on. I have tried this with an else, elsif and finally a separate if, but it ends up returning what I know to be false data meaning rmt54 does not own abcd1234. Its goal or purpose scans through all the devices that an application owns, creates a HoA with the dev name being the key (rmt#) and its two values, two 8 byte strings (\w+) telling me if it was found and what rmt owns what wwns. Any other critiques welcome, thank you!

use strict; use warnings; #use Data::Dumper; my $lsdev = "/usr/sbin/lsdev -c tape"; my $lsattr = "/usr/sbin/lsattr -El"; my (@rmts, %wwns, $rmtkey, @input2, @fileinput); sub _compare_match_WWPN { die "no parameter!\n" unless @_; my ($w_ref) = @_; my (@w) = @{ $w_ref }; open (LSDEV, "-|", $lsdev) or die "'lsdev' was not opened $!\n"; for my $t (<LSDEV>) { push @rmts, +(split(" ", $t, 0))[0]; } for my $r (@rmts) { push @{ $wwns{$r}}, +(split(/\s+|0x/, `$lsattr $r -a node_name +`, 0))[2]; push @{ $wwns{$r}}, +(split(/\s+|0x/, `$lsattr $r -a ww_name`, + 0))[2]; } OUTER: foreach my $rmtkey (sort keys %wwns) { for my $indx ( 0 .. $#{$wwns{$rmtkey}} ) { for my $name ( @w ) { if ( $name =~ /^$wwns{$rmtkey}[$indx]$/i ) { print "Found '${name}' that belongs to $rmtkey\n"; next OUTER; } ### HERE IS WHERE I TRIED ELSE, etc. CONDITIONS ### } } } return; } ##-- MAIN --## print "\nTSM Device ID Search\nPlease enter cli or file: "; while ( chomp ( my $input = lc(<>) ) ) { last if $input =~ /\s+$/; if ( $input eq "cli" ) { INNER: print "\nEnter your wwns to search for? More than one, +comma seperated: ---> "; while ( chomp ( my $input2 = lc(<>) ) ) { last if $input2 !~ /\w+/; @input2 = split(/,|\s+/, $input2); _compare_match_WWPN( \@input2 ); print "\nDo you want to restart this search? ---> "; chomp ( my $input3 = lc(<>) ); goto INNER if $input3 eq "yes" or $input3 eq "y"; exit 0; } } elsif ( $input eq "file" ) { INNER2: print "\nEnter the fullpath+filename, Enter to end? -- +-> "; while ( chomp ( my $input4 = lc(<>) ) ) { open ( F, "+<", $input4 ) or die "'$input4' file was not f +ound/opened $!\n"; while (<F>) { push @fileinput, split(/,|\s+/, lc($_)); } _compare_match_WWPN( \@fileinput ); print "\nDo you want to restart this search? ---> "; chomp ( my $input5 = lc(<>) ); goto INNER2 if $input5 eq "yes" or $input5 eq "y"; exit 0; } } else { warn "\nI need input of file or cli, exiting.\n$!\n"; die; } } _OUTPUT_ # perl tsm_IDstorage_devs.pl TSM Device ID Search Please enter cli or file: cli Enter your wwns to search for? More than one, comma seperated: ---> 21 +000024ff66941c,2009000g123456ff Found '21000024ff66941c' that belongs to rmt137 Found '21000024ff66941c' that belongs to rmt138 Found '21000024ff66941c' that belongs to rmt139 Found '21000024ff66941c' that belongs to rmt140 Found '21000024ff66941c' that belongs to rmt141 Found '21000024ff66941c' that belongs to rmt142 Found '21000024ff66941c' that belongs to smc14 _DATA_STRUCTURE_ $VAR1 = { 'rmt54' => [ '500143802483d27c', '500143802483d27d' ], 'rmt42' => [ '500143802483cfe2', '500143802483cfe5' ], };

Replies are listed 'Best First'.
Re: search HoA-reference
by stevieb (Canon) on Jan 24, 2018 at 22:04 UTC

    I quickly re-wrote the logic in the sub to iterate over the user-args in the outer loop, then do the loop over the structure on the inner loop. This makes it a bit easier to achieve what I believe you want.

    First, I removed the re-assignment of the parameters to avoid unnecessary overhead, and just use the aref directly in the code. Other than the restructuring, I've also changed from iterating over the inner array within the hash to just using grep instead. Note I've also added a $found flag. This is how we track whether the WWN has been found or not within the entire structure. This variable gets reset each time we look for a new user-supplied WWN.

    The code assumes that only a single WWN can be found in the entire structure. If it can be in numerous places (which I can't see how and would indicate larger issues I would think), then change the last to a next inside the grep condition.

    sub _compare_match_WWPN { die "no parameter!\n" unless @_; my ($w_ref) = @_; for my $name (@{ $w_ref }){ my $found; for my $rmtkey (sort keys %wwns){ if (grep {$name eq $_} @{ $wwns{$rmtkey} }){ print "Found '${name}' that belongs to $rmtkey\n"; $found = 1; last; } } if (! $found){ print "$name not found!\n"; } } return; }

    Output:

    Enter your wwns to search for? More than one, comma seperated: ---> 20 +09000g123456ff,500143802483cfe5 2009000g123456ff not found! Found '500143802483cfe5' that belongs to rmt42