http://www.perlmonks.org?node_id=756430

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

In the following code, the script should run through a csv file of data, Each line should match the conditions of the if statements near the bottom one or more times.

For each match I output a line that contains all of the commonRecords and the records of the applicable if clause. These then get pushed on to an array for later loading into a db.

In the dumper output, the last record correctly shows up as VAR1 with appropriate key => value mappings. Everything else shows up as VAR2 thru VAR160, where do I need to properly postion my push statements?

my $producer= ""; my %opts; getopts("a:c:d:s:", \%opts); $opts{'a'} or usage(); $opts{'d'} or usage(); $opts{'s'} or usage(); open(ASSET_DATA, "<$opts{'a'}") or usage("Unable to open data file $op +t{'a'}"); open(REMEDY_DATA, "<$opts{'d'}") or usage("Unable to open data file $o +pt{'d'}"); my @icrs_array = (); my @remedy_array = (); my $records = []; my $list = []; my %commonRecord = (); my %record = (); my $aerial = []; my $inground = []; my $infacility = []; my $inventory = []; while(<REMEDY_DATA>) { chomp; @remedy_list = split/,/; %record = (); $commonRecord{"VulnerabilityId"}= $remedy_list[0]; print $commonRecord{"VulnerabilityId"} . "\n"; $datestring= "2009-01-14 13:14:01"; $commonRecord{"Date"}= $datestring; $commonRecord{"Source"}= "Remedy"; $commonRecord{"Url"}= "http://cablevision.com/cgi/? foo"; $commonRecord{"ReportConfidence"} = 100; $commonRecord{"CompensatingControls"} = 100; $commonRecord{"AerialScalingFactor"} = &scale_aerial($remedy_l +ist[7],$remedy_list[9]); $commonRecord{"InGroundScalingFactor"} = &scale_inground ($rem +edy_list[7],$remedy_list[9]); $commonRecord{"InFacilityScalingFactor"} = &scale_infacility($ +remedy_list[7],$remedy_list[9]); $commonRecord{"InventoryScalingFactor"} = &scale_numberassets +($remedy_list[10]); my $aa=100; my $av = 100; $remedy_issue = $remedy_list[7]; if ($remedy_issue =~ m/vandalism/i) { my $vandal = 50; } else { $vandal = 100; } $commonRecord{"AccessComplexity"} = $vandal; $commonRecord{"AuthenticatedAccess"} = $aa; $commonRecord{"AccessVector"} = $av; $commonRecord{"Exploitability"} = int(($aa * $av * $vandal)/10 +000); my $noc_calls = 2; my $truck_rolls = 0; my $ticket_bounces = 1; my $credits_issued = 0; my $noc_call_cost = 25; my $truck_roll_cost = 75; my $ticket_bounce_cost = 30; my $avg_credit_cost =25; $commonRecord{"NOC_Call_Cost"} = $noc_call_cost; $commonRecord{"Truck_Roll_Cost"} = $truck_roll_cost; $commonRecord{"Ticket_Bounce_Cost"} = $ticket_bounce_cost; $commonRecord{"Avg_Credit_Cost"} = $avg_credit_cost; $commonRecord{"NOC_calls"} = $noc_calls; $commonRecord{"Truck_Rolls"} = $truck_rolls; $commonRecord{"Ticket_Bounces"} = $ticket_bounces; $commonRecord{"Credits"} = $credits_issued; my $duration; if (($remedy_list[14] ne "") && ($remedy_list[14] ne 0)) { $duration = $remedy_list[14]; } else { $duration = 1; } my $iO_subs; my $OOL_subs; my $analog_subs; if (($remedy_list[20] ne "") && ($remedy_list[20] ne 0)) { $iO_subs = $remedy_list[20]; %record = (); %record = %commonRecord; $record{"VulnerabilityId"} = join("_",$record{"Vulnera +bilityId"},"iO"); $record{"ImpactCost"} = int(($duration * $iO_subs)/864 +00); $record{"ImpactCostType"} = "Reputational"; $record{"PotentialEffect"} = "Outage"; push @{$records}, %record; } if (($remedy_list[21] ne "") && ($remedy_list[21] ne 0)) { $OOL_subs = $remedy_list[21]; %record = (); %record = %commonRecord; $record{"VulnerabilityId"} = join("_",$record{"Vulnera +bilityId"},"OOL"); $record{"ImpactCost"} = int(($duration * $OOL_subs)/86 +400); $record{"ImpactCostType"}= "Reputational"; $record{"PotentialEffect"}= "Outage"; push @{$records}, \%record; } if (($remedy_list[25] ne "") && ($remedy_list[25] ne 0)) { $analog_subs = $remedy_list[25]; %record = (); %record = %commonRecord; $record{"VulnerabilityId"} = join("_",$record{"Vulnera +bilityId"},"Analog"); $record{"ImpactCost"} = int(($duration * $analog_subs) +/86400); $record{"ImpactCostType"}= "Reputational"; $record{"PotentialEffect"}= "Outage"; push @{$records}, \%record; } else { print "Other\n"; %record = (); %record = %commonRecord; $record{"VulnerabilityId"} = join("_",$record{"Vulnera +bilityId"},"Other"); $record{"ImpactCost"} = 0; $record{"ImpactCostType"}= "Reputational"; $record{"PotentialEffect"}= "Outage"; push @{$records}, \%record; } }; print Dumper @{$records}; close(REMEDY_DATA);

Note that the data in the VAR1 statement is the LAST record processed from the Remedy file...What I want is VAR1 - VAR13, each looking like VAR1 here.

$VAR1 = { 'Truck_Rolls' => 0, 'AerialScalingFactor' => '60', 'VulnerabilityId' => 'UTT000000160928_Analog', 'ReportConfidence' => 100, 'NOC_Call_Cost' => 25, 'Truck_Roll_Cost' => 75, 'Credits' => 0, 'CompensatingControls' => 100, 'InFacilityScalingFactor' => '10', 'AccessVector' => 100, 'Avg_Credit_Cost' => 25, 'Source' => 'Remedy', 'Ticket_Bounce_Cost' => 30, 'InGroundScalingFactor' => '30', 'ImpactCostType' => 'Reputational', 'NOC_calls' => 2, 'ImpactCost' => 45, 'AuthenticatedAccess' => 100, 'Date' => '2009-01-14 13:14:01', 'AccessComplexity' => 100, 'Ticket_Bounces' => 1, 'InventoryScalingFactor' => 1, 'Url' => 'http://cablevision.com/cgi/? foo', 'Exploitability' => 100, 'PotentialEffect' => 'Outage' }; $VAR2 = 'Truck_Rolls'; $VAR3 = 0; $VAR4 = 'AerialScalingFactor'; $VAR5 = '60'; $VAR6 = 'VulnerabilityId'; $VAR7 = 'UTT000000166730_iO'; $VAR8 = 'ReportConfidence'; $VAR9 = 100; $VAR10 = 'NOC_Call_Cost'; $VAR11 = 25; $VAR12 = 'Truck_Roll_Cost'; $VAR13 = 75; $VAR14 = 'Credits'; $VAR15 = 0; $VAR16 = 'CompensatingControls'; $VAR17 = 100; $VAR18 = 'InFacilityScalingFactor'; $VAR19 = '10'; $VAR20 = 'AccessVector'; $VAR21 = 100; $VAR22 = 'Avg_Credit_Cost'; $VAR23 = 25; $VAR24 = 'Source'; $VAR25 = 'Remedy'; $VAR26 = 'Ticket_Bounce_Cost'; $VAR27 = 30; $VAR28 = 'InGroundScalingFactor'; $VAR29 = '30'; $VAR30 = 'ImpactCostType'; $VAR31 = 'Reputational'; $VAR32 = 'NOC_calls'; $VAR33 = 2; $VAR34 = 'ImpactCost'; $VAR35 = 2; $VAR36 = 'AuthenticatedAccess'; $VAR37 = 100; $VAR38 = 'Date'; $VAR39 = '2009-01-14 13:14:01'; $VAR40 = 'AccessComplexity'; $VAR41 = 100; $VAR42 = 'Ticket_Bounces'; $VAR43 = 1; $VAR44 = 'InventoryScalingFactor'; $VAR45 = 1; $VAR46 = 'Url'; $VAR47 = 'http://cablevision.com/cgi/? foo'; $VAR48 = 'Exploitability'; $VAR49 = 100; $VAR50 = 'PotentialEffect'; $VAR51 = 'Outage'; $VAR52 = $VAR1; $VAR53 = $VAR1; $VAR54 = 'Truck_Rolls'; $VAR55 = 0; $VAR56 = 'AerialScalingFactor'; $VAR57 = '60'; $VAR58 = 'VulnerabilityId'; $VAR59 = 'UTT000000160745_iO'; $VAR60 = 'ReportConfidence'; $VAR61 = 100; $VAR62 = 'NOC_Call_Cost'; $VAR63 = 25; $VAR64 = 'Truck_Roll_Cost'; $VAR65 = 75; $VAR66 = 'Credits'; $VAR67 = 0; $VAR68 = 'CompensatingControls'; $VAR69 = 100; $VAR70 = 'InFacilityScalingFactor'; $VAR71 = '10'; $VAR72 = 'AccessVector'; $VAR73 = 100; $VAR74 = 'Avg_Credit_Cost'; $VAR75 = 25; $VAR76 = 'Source'; $VAR77 = 'Remedy'; $VAR78 = 'Ticket_Bounce_Cost'; $VAR79 = 30; $VAR80 = 'InGroundScalingFactor'; $VAR81 = '30'; $VAR82 = 'ImpactCostType'; $VAR83 = 'Reputational'; $VAR84 = 'NOC_calls'; $VAR85 = 2; $VAR86 = 'ImpactCost'; $VAR87 = 3; $VAR88 = 'AuthenticatedAccess'; $VAR89 = 100; $VAR90 = 'Date'; $VAR91 = '2009-01-14 13:14:01'; $VAR92 = 'AccessComplexity'; $VAR93 = 100; $VAR94 = 'Ticket_Bounces'; $VAR95 = 1; $VAR96 = 'InventoryScalingFactor'; $VAR97 = 1; $VAR98 = 'Url'; $VAR99 = 'http://cablevision.com/cgi/? foo'; $VAR100 = 'Exploitability'; $VAR101 = 100; $VAR102 = 'PotentialEffect'; $VAR103 = 'Outage'; $VAR104 = $VAR1; $VAR105 = $VAR1; $VAR106 = $VAR1; $VAR107 = $VAR1; $VAR108 = 'Truck_Rolls'; $VAR109 = 0; $VAR110 = 'AerialScalingFactor'; $VAR111 = 1; $VAR112 = 'VulnerabilityId'; $VAR113 = 'UTT000000160921_iO'; $VAR114 = 'ReportConfidence'; $VAR115 = 100; $VAR116 = 'NOC_Call_Cost'; $VAR117 = 25; $VAR118 = 'Truck_Roll_Cost'; $VAR119 = 75; $VAR120 = 'Credits'; $VAR121 = 0; $VAR122 = 'CompensatingControls'; $VAR123 = 100; $VAR124 = 'InFacilityScalingFactor'; $VAR125 = 1; $VAR126 = 'AccessVector'; $VAR127 = 100; $VAR128 = 'Avg_Credit_Cost'; $VAR129 = 25; $VAR130 = 'Source'; $VAR131 = 'Remedy'; $VAR132 = 'Ticket_Bounce_Cost'; $VAR133 = 30; $VAR134 = 'InGroundScalingFactor'; $VAR135 = 1; $VAR136 = 'ImpactCostType'; $VAR137 = 'Reputational'; $VAR138 = 'NOC_calls'; $VAR139 = 2; $VAR140 = 'ImpactCost'; $VAR141 = 9; $VAR142 = 'AuthenticatedAccess'; $VAR143 = 100; $VAR144 = 'Date'; $VAR145 = '2009-01-14 13:14:01'; $VAR146 = 'AccessComplexity'; $VAR147 = 100; $VAR148 = 'Ticket_Bounces'; $VAR149 = 1; $VAR150 = 'InventoryScalingFactor'; $VAR151 = 1; $VAR152 = 'Url'; $VAR153 = 'http://cablevision.com/cgi/? foo'; $VAR154 = 'Exploitability'; $VAR155 = 100; $VAR156 = 'PotentialEffect'; $VAR157 = 'Outage'; $VAR158 = $VAR1; $VAR159 = $VAR1; $VAR160 = $VAR1;

Thanks all.

Scott

Replies are listed 'Best First'.
Re: pushing onto array is not working as intended..
by kyle (Abbot) on Apr 08, 2009 at 19:38 UTC

    This line:

    push @{$records}, %record;

    ...should be:

    push @{$records}, \%record;

    ...as you have everywhere else.

    Update: Actually, that's not going to do what you want either. Change them all to:

    push @{$records}, { %record };

    With what you have, you'll end up with an array of references to the same hash. You want to construct a new hash every time you push, and the above syntax will do that.

      Seems to me you fixed the wrong line in your update. I consider
      %record = (); ... push @{$records}, { %record };
      much worse than
      my %record; ... push @{$records}, \%record;
      Yes, that's exactly what I wanted.
      The syntax is NOT second nature yet...

      Thank you very much!

      Scott...
Re: pushing onto array is not working as intended..
by kennethk (Abbot) on Apr 08, 2009 at 19:46 UTC

    You'd do well to use strict;use warnings. Adding those pragmas I uncover the following issues in your code:

    1. Lines 10 and 12: Your error message accesses %opt instead of %opts
    2. Line 56: By using my within the scope of an if block, you are scoping it to the block; hence, the value you assign (50) is not visible outside that block, and you'll get an undef or old data.

    This of course was not your problem here, but are obviously bugs you hadn't found yet.

Re: pushing onto array is not working as intended..
by gwadej (Chaplain) on Apr 08, 2009 at 19:39 UTC

    Your output looks like a hash or list was pushed on the array instead of a hash reference. Sure enough, the first if has:

    push @{$records}, %record;
    instead of
    push @{$records}, \%record;

    Note the missing backslash.

    G. Wade