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

I am going to by the llama later today. In the meantime, I need some basic help with my hash. I had a line that was originally:

server,1212,123123,12341234

I could have several lines for each server and I needed to add the values while maintaining the CSV format. I have added some string data to the end of the lines that I would like to maintain as well. The code below however, complains that the data is not numeric and seems to drop the non-numeric data. How can I modify it to add the numeric data together while maintaining the non-numeric data?

while (<CSV_OUT>) { chomp; my @line = split /,/; my $name = shift @line; if (exists $servers{$name}) { foreach my $index (0..$#line) { $servers{$name}[$index] += $line[$index]; } } else { $servers{$name} = [@line]; } }

example data source:

cihcrppmon02,standard_unix_corp-cis_shared,1703995999752,133635610485, +31055995112,12.75,54.8, ghnbu, gh_nbu02 ovpip02,standard_unix_corp-cis_shared,41851038572,14933570508,38353867 +32,2.80,10.91,ghnbu, gh_nbu02 cihcispapp247,standard_unix_corp-cis_shared,190635017908,24806407611,9 +442867181,7.68,20.19,ghnbu, gh_nbu02 wavmd003,standard_unix_corp-cis_shared,2760141244,594115253,299382152, +4.65,9.22,ghnbu, gh_nbu02

Thanks for all of your help!!

Replies are listed 'Best First'.
Re: Adding numeric values while keeping string values
by ikegami (Patriarch) on Aug 17, 2009 at 16:03 UTC

    What do you expect "standard_unix_corp-cis_shared"+"standard_unix_corp-cis_shared" to give? You shouldn't be adding all the fields together.

    foreach my $index (0..$#line)
    should be something like
    foreach my $index (4,5)

    By the way,
    $servers{$name} = [@line];
    needlessly copies @line. Simply use
    $servers{$name} = \@line;
    since my @line; will create a new var for you every pass.

Re: Adding numeric values while keeping string values
by JavaFan (Canon) on Aug 17, 2009 at 16:43 UTC
    use Scalar::Util 'looks_like_number'; ... for (my $index = 0; $index < @line; $index++) { $servers{$name}[$index] += $line[$index] if looks_like_number($servers{$name}[$index]) && looks_like_number($line[$index]); } ...
Re: Adding numeric values while keeping string values
by ack (Deacon) on Aug 17, 2009 at 17:59 UTC

    As other Monks have noted, the problem is that in some instances of $servers{$name}[$index] += $line[$index] you're trying to do numeric addition on non-numeric, string, data.

    JavaFan suggested using the CPAN module Scalar::Util's function looks_like_number or you can use Scalar::Util::Numeric's function isnum($val) where the $val is the scalar that you're checking to see if it's a number.

    I have coded up a quick example using the Scalar::Util::Numeric as an example for you to see how it might be used to solve the problem you alluded to in your inquiry.

    My example codes is as follows:

    #!/user/bin/perl use strict; use warnings; use Scalar::Util::Numeric qw(:all); my %servers = ( 'cihcrppmon02'=>['standard_unix_corp-cis_shared',170399 +5999752,133635610485,31055995112,12.75,54.8,'ghnbu','gh_nbu02'], 'ovpip02' =>['standard_unix_corp-cis_shared',418510 +38572,14933570508,3835386732,2.80,10.91,'ghnbu','gh_nbu02'], ); my @input = ( "cihcrppmon02,standard_unix_corp-cis_shared,1703995999752,133635610 +485,31055995112,12.75,54.8, ghnbu, gh_nbu02\n", "ovpip02,standard_unix_corp-cis_shared,41851038572,14933570508,3835 +386732,2.80,10.91,ghnbu, gh_nbu02\n", "cihcispapp247,standard_unix_corp-cis_shared,190635017908,248064076 +11,9442867181,7.68,20.19,ghnbu, gh_nbu02\n", "wavmd003,standard_unix_corp-cis_shared,2760141244,594115253,299382 +152,4.65,9.22,ghnbu, gh_nbu02\n", ); foreach my $line_in (@input){ chomp($line_in); my @line = split(/,/,$line_in); my $name = shift @line; if(exists $servers{$name}){ foreach my $index (0..$#line){ if(isnum($line[$index]) && isnum($servers{$name}[$index])){ $servers{$name}[$index] += $line[$index]; } } } else { $servers{$name} = [@line]; } } foreach my $name (keys %servers){ print "$name: " . join(" ",@{$servers{$name}}) . "\n"; } exit(0);

    This produces the results:

    cihcrppmon02: standard_unix_corp-cis_shared 3407991999504 2672712209 +70 62111990224 25.5 109.6 ghnbu gh_nbu02 ovpip02: standard_unix_corp-cis_shared 83702077144 29867141016 7670 +773464 5.6 21.82 ghnbu gh_nbu02 cihcispapp247: standard_unix_corp-cis_shared 190635017908 2480640761 +1 9442867181 7.68 20.19 ghnbu gh_nbu02 wavmd003: standard_unix_corp-cis_shared 2760141244 594115253 299382 +152 4.65 9.22 ghnbu gh_nbu02

    I had to put your example input into an array to simulate your input stream. In order to show that the numeric part of the example works, I also pre-populated the hash %servers with a couple of entries (just copies of your input example for a couple of the servers) so that the numeric code would be exercised).

    I didn't know what you intended to do if various entries for a particular server had different non-numeric data (for example, if for the server 'cihcrppmon02' you had 'ghnbu' in one entry and perhaps something like 'gxfoo' in another). So I just assumed that the non-numeric data in all entries would be the same. This is probably not quite what you had in mind (perhaps you would want to append the added information or something like that); but you didn't give any indication what you wanted to do with such data.

    I hope this helps to show at least one strategy for you.

    ack Albuquerque, NM

      UPDATE: Sorry. I forgot the post-tag </readmore>. I didn't intend to make such a long post for viewing.

      I sure wish the <readmore> tags would show up in the "preview."

      ack Albuquerque, NM

        The title= part of <readmore title="..."> is still missing and that makes visible the code, at least for me.

Re: Adding numeric values while keeping string values
by dwm042 (Priest) on Aug 17, 2009 at 18:53 UTC
    I look at this questions and the solutions, and the only thing going through my mind currently is, how would this code deal with the same server appearing in this file more than once?

    The code being offered by the Monks works fine if the servers are unique, but it might be worth the OP's time to deal with the case of servers appearing multiple times in the data file.