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

I'm new to using perl. Basically what I'm trying to do is slice up a csv file and perform two actions with it, one iterate through certain columns and confirm DNS entries exist for certain systems and they are accurate and output anything that doesn't match and secondly generate nagios configuration files for any entry which has an IP address. I'm stuck at this point, my code states "Use of uninitialized value $hostip in string at C:/Users/akuncewitch/workspace/Sec Ops Engineering Toolkit/nagiosgen.pl line 15, <F> line 1." When I run it but I have no idea what I'm missing. I've written several fairly simple Perl scripts that sliced up csv and even performed actions in a loop, so I'm not sure what I'm missing this time.

perl 5, version 12, subversion 4 (v5.12.4) built for MSWin32-x64-multi-thread Binary build 1205 294981 provided by ActiveState http://www.ActiveState.com Built Jun 20 2011 18:11:54

use warnings; #Read Security Engineering Inventory CSV Export and puke @ failure my $file = 'C:/perl64/seceng.csv'; my $hostpath = 'C:/perl64/nagios/hosts/'; #my $hostpath = '/usr/local/nagios/etc/objects/hosts/'; open (F, $file) || die ("Could not open $file!"); while (<F>) { @fields = split(',', $_); $hostname = $fields[3]; $hostip = $fields[5]; if(-e "$hostip"){ open (HOST, 'C:/perl64/nagios/hosts/' . $hostname) || die "Couldn' +t open: $!"; printf HOST "define host\{"; printf HOST "use linux-server;\n"; printf HOST "host_name $host;\n"; printf HOST "alias $host;\n"; printf HOST "address $hostip;\n"; printf HOST "\}"; } } close F;

Replies are listed 'Best First'.
Re: Question on loops and variables
by keszler (Priest) on Oct 12, 2011 at 21:42 UTC

    Without your data I can only guess that split is giving you an empty $fields[5] from one of the data rows.

    There are lots of pitfalls in parsing CSV, which is why you'll have numerous responses telling you to use one of the many CSV modules on CPAN. My recommendation is Text::CSV_XS.

      When I run the loop as

      while (<F>) { @fields = split(',', $_); $hostname = $fields[3]; my $hostip = $fields[5]; print "$hostname\n"; print "$hostip\n"; }
      it outputs data appropriately so it seems it has something to do with the loop but i don't understand what. Oh, I forgot to add thank you very much for the response! :)

        Are you sure that warnings are enabled in your second script, too? If not, it would explain that you don't get any warnings. I don't see how your second script would change anything.

        Note that the original error message even tells you the line number of your data file where the warning is generated with "Use of initialized value ... <F> line 1.". So check the first two lines of your data file (I don't know if the count starts from 0 or 1).

        Also assuming the problematic line in the file were an empty line, even $hostname would be an empty string (but not undefined) and all you would see with your prints would be two empty lines in the beginning of the output, so you might have missed the problematic output in your second script. Either use

        print "host: $hostname, <$hostip>\n";

        or even better use Data::Dumper:

        use Data::Dumper; ... print Dumper(\$hostname,\$hostip),"\n";

        Data::Dumper may look like overkill for now, but as soon as you start to use more complicated data structures you will find it the best thing since sliced bread

        When I run the loop as ... it outputs data appropriately ...

        I doubt it. Just to drive home the point of jethro's reply above, consider:

        >perl -le "use warnings; ;; $empty_string = ''; @ra = split ',', $empty_string; ;; $foo = $ra[3]; $bar = $ra[5]; print qq{'$foo' '$bar'}; " Use of uninitialized value $foo in concatenation (.) or string at... Use of uninitialized value $bar in concatenation (.) or string at... '' ''

        And once again, do yourself a favor and  use warnings; and  use strict;

Re: Question on loops and variables
by Marshall (Canon) on Oct 13, 2011 at 05:29 UTC
    A couple of things look suspicious to me...

    1. line 15 of your code  if(-e "$hostip"){ That is a file test operator that see if a file "$hostip" exists in the current working directory. Then your code goes on to open some other file. Is this file test what you intended to do?

    2. The most common cause of "uninitialized value" is a blank line in the input file. Add a print "input=>$_"; line in your while loop to see what each line actually is that is being read. I usually add a "next if /^\s*$/;" to skip blank lines.

    3. I see the path: C:/Perl64 That is the default installation directory for 64 bit Active Perl. I may not be understanding what you have - I don't see how C:/perl64/nagios/hosts/ is an Active State created directory or file. But I strongly recommend that you not write any of your own data in C:/Perl64 or anything underneath it. I would consider that whole directory structure as "belonging" to ActiveState.

Re: Question on loops and variables
by Kc12349 (Monk) on Oct 12, 2011 at 22:10 UTC

    A sample of your data would be helpful in this case. I would also advise you to look into lexical filehandles as this in now pretty standard in modern perl. You could also look at using the autodie module to avoid some unneeded clutter.