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

I'm still learning Perl and I'm a newbie. I have gotten the below hashes to store the information from the .csv files that I want to read and do something with. But, now I'm stuck on getting the information from the %firms into the $upload variable that I want to add and print out to a new .csv file. I would also like to compare the keyvalues to see where I am missing information that is not in the %firms hash and is in the %acs hash. Can someone please help me with figuring out why my hashes aren't working properly in the foreach statements? Any help on this is greatly appreciated. I feel like I'm right there, but I have never tried to work with 2 different files and trying to piece information from both to a completely new file.

#!/perl/bin/perl use strict; use warnings; use Data::Dumper; open FH1, "<", "namecleanupapcdevices1.csv" or die $!; open FH2, "<", "acs_import.csv" or die $!; my (%firms, %acs); my $testrun = ''; my $recnum = 1; my $recnum1 = 1; my ($upload, $text); while (defined( my $line = <FH1> ) ){ chomp $line; my ($type, $location1, $location2, $label, $model, $fi +rmware, $hostname, $contact, $serial, $ip, $mac) = split ',', $line, +12; #$location1 =~ s/"?//g; #$location2 =~ s/"?//g; $label =~ s/\(.+\)?//g; $firms{$recnum}{type} = $type; $firms{$recnum}{location1} = $location1.",".$location2 +; #$firms{$recnum}{location2} = $location2; $firms{$recnum}{label} = $label; $firms{$recnum}{model} = $model; $firms{$recnum}{firmware} = $firmware; $firms{$recnum}{hostname} = $hostname; $firms{$recnum}{contact} = $contact; $firms{$recnum}{serial} = $serial; $firms{$recnum}{ip} = $ip; $firms{$recnum}{mac} = $mac; $recnum++; } while (defined( my $line2 = <FH2> ) ){ chomp $line2; my ($name64, $update64, $description, $subnet, $suppor +t_radius, $radius_secret, $port, $support_keywrap, $keywrap_KEK, $key +wrap_mack, $keywrap_display, $support_TACACS, $tacacsSecret, $singlec +onnect, $legacyTACACS, $Location_String, $Device_Type_String, $System +_Owner) = split ',', $line2, 18; $subnet =~ s/\/32?//g; $acs{$recnum1}{name64} = $name64; $acs{$recnum1}{update64} = $update64; $acs{$recnum1}{description} = $description; $acs{$recnum1}{subnet} = $subnet; $acs{$recnum1}{support_radius} = $support_radius; $acs{$recnum1}{radius_secret} = $radius_secret; $acs{$recnum1}{port} = $port; $acs{$recnum1}{support_keywrap} = $support_keywrap; $acs{$recnum1}{keywrap_KEK} = $keywrap_KEK; $acs{$recnum1}{keywrap_mack} = $keywrap_mack; $acs{$recnum1}{keywrap_display} = $keywrap_display; $acs{$recnum1}{support_TACACS} = $support_TACACS; $acs{$recnum1}{tacacsSecret} = $tacacsSecret; $acs{$recnum1}{singleconnect} = $singleconnect; $acs{$recnum1}{legacyTACACS} = $legacyTACACS; $acs{$recnum1}{Location_String} = $Location_String; $acs{$recnum1}{Device_Type_String} = $Device_Type_Stri +ng; $acs{$recnum1}{System_Owner} = $System_Owner; $recnum1++; } foreach $recnum(keys %firms){ print Dumper $recnum; $firms{$recnum}{label} = $acs{$recnum1}{update64}; $firms{$recnum}{location1} = $acs{$recunm1}{description}; } foreach $recnum1(keys %acs){ print Dumper $recnum1; #foreach $recnum(sort keys %firms){ #if (($acs{$recnum1}{name64} = $firms{$recnum}{label}) + && ($firms{$recnum}{ip} = $acs{$recnum1}{subnet})){ $upload .= "$acs{$recnum1}{name64},$firms{$recnum}{lab +el},$firms{$recnum}{location1},$acs{$recnum1}{subnet}/32,$acs{$recnum +1}{support_radius},$acs{$recnum1}{radius_secret},$acs{$recnum1}{port} +,$acs{$recnum1}{support_keywrap},$acs{$recnum1}{keywrap_KEK},$acs{$re +cnum1}{keywrap_mack},$acs{$recnum1}{keywrap_display},$acs{$recnum1}{s +upport_TACACS},$acs{$recnum1}{tacacsSecret},$acs{$recnum1}{singleconn +ect},$acs{$recnum1}{legacyTACACS},$acs{$recnum1}{Location_String},$ac +s{$recnum1}{Device_Type_String},$acs{$recnum1}{System_Owner}\n"; } # elsif ($acs{$recnum1}{name64} != $firms{$recnum}{labe +l}){ # print "--- Not Found ---\n"; # print "Name: $acs{$recnum1}{name64}\nSubnet: $acs{$re +cnum1}{subnet}\n"; # next; # } print "completed\n"; open OutFile, ">", "ACS_import_list.csv" or die $!; print OutFile $upload; close OutFile; close FH1; close FH2;\

Thanks, Brandon

Replies are listed 'Best First'.
Re: Need Help with foreach statement?????
by graff (Chancellor) on Oct 01, 2015 at 21:52 UTC
    In your first "foreach" loop (just after the two while loops reading the two input files), you are not changing the value of $recnum1, which means that on every iteration of this for loop, you're using the last value that was assigned to that variable, which is the last record actually read plus one (i.e. a non-existent record in your %acs hash).

    Apart from that, it looks like you're expecting your two input files to have the same number of lines, and that there's some trustworthy relationship between the corresponding lines of the two files (file1 line1 goes with file2 line1, and so on, to the end of each file). If that's what you're assuming, are you sure it's really true for those two input files?

    Also, are you sure that your "csv" files do not contain commas embedded in field values? ("Proper" csv format would put quotes around fields that contain one or more commas as part of the data, and you'd want to use Text::CSV when you have csv files like this.)

Re: Need Help with foreach statement?????
by GotToBTru (Prior) on Oct 02, 2015 at 03:08 UTC

    Using a sequential integer as the key for your hashes %firms and %acs is a give-away that you really want an array, not a hash.

    my (@firms); while (defined( my $line = <FH1> ) ){ chomp $line; my (%hash); my ($type, $location1, $location2, $label) = split ',', $line, 12; $hash{type} = $type; $hash{label} = $label; push @firms, \%hash; }

    Update: suggestion for a more compact way to extract the data from array of hashes for uploading (using an hash slice):

    @fields=qw(name64 label location1 subnet support_radius); for(my $i=0; $i<=$#firms; $i++) { $firms[$i]->{subnet} /= 32; $upload .= sprintf "%s\n", join ',', @{$firms[$i]}{@fields}; }

    Update 2: as pointed out by Albannach, the commas did not belong in the array definition

    Dum Spiro Spero
Re: Need Help with foreach statement?????
by NetWallah (Canon) on Oct 01, 2015 at 23:16 UTC
    Untested:
    #!/perl/bin/perl use strict; use warnings; use Data::Dumper; use Text::CSV; open my $fh1, "<", "namecleanupapcdevices1.csv" or die $!; open my $fh2, "<", "acs_import.csv" or die $!; my $csv = Text::CSV->new ( { binary => 0 } ) or die "Cannot use CSV: ".Text::CSV->error_diag (); $csv->column_names ( qw| type location1 location2 label model firmware +hostname contact serial ip mac| ); # Set column names for getline_hr () my $firms = $csv->getline_hr_all ($fh1); close $fh1; $csv->column_names ( qw|name64 update64 description subnet support_radius radius_secr +et port support_keywrap keywrap_KEK keywrap_mack keywrap_display support_TACACS tacacsSecret singleconnect leg +acyTACACS Location_String Device_Type_String System_Owner| ); my $row=0; while (my $acs = $csv->getline_hr ($fh2)){ my $firmrow = $firms->[$row++]; # print out info from print $firmrow->{whatever}, $acs->{acs_stuff}; } close $fh2;

            Software efficiency halves every 18 months, thus compensating for Moore's Law.