Count script wrapper help

I have this a code that I got help with for another task. I since tried to modify it to work on this task.

I need someones expertise to modify it slightly and I am not sure where to start or yet fully understand the logic.

I am trying to get a script to read my m-names.txt which has lots of
167.0.0.0/8
168.0.0.0/8
192.0.0.0/8

I need to strip the / part and only use the subnet address:
167.0.0.0

Then feed it into a cli called getobjectlst.exe with a -a flag that puts the subnet address from m-names.txt

This produces a report that looks like:

"167.227.31.14" "brs2002_204" "Server" "Static" "dc.dk.sark.com"
"167.227.31.15" "brs2005_284" "Server" "Static" "dc2.dk.sark.com"
"167.227.31.16" "brs2003" "Server" "Static" "dc4.dk.sark.com"

I am intrested in the 4th field entry value and how many (count) they are per $subnet=

I get a report on how many types etc... works great,

But I need it to also do another task, when I run this script I could run into a senerio like this:
Error 48: This subnet does not exist.
146.149.0.0
getobjectlst.exe :146.149.0.0: Error code = 48

If I get an message like that, I need the script to engage in another routine;
If that subnet has that error 48" this subnet does not exist" then and run another cli called "getsubnetlst.exe" like so

./getsubnetlst.exe -u Xxx -p Xxx -a 146.149.0.0 -t netwrok -o rich

This will produce relatively the same output as in the first code:
"East" "146.149.1.0" "N" "" "146.149.0.0" " " " " "255.255.255.128"
"West-Subnet" "146.149.16.0" "Y" "" "146.149.0.0" " " " " "255.255.255.252"
"North Subnet" "146.149.16.128" "Y" "" "146.149.0.0" " " " " "255.255.255.240"
"Asia D-NAT" "146.149.22.0" "Y" "" "146.149.0.0" " Japan" " " "255.255.255.0"

Then I need to run the same cli getobjectlst.exe and reference the subnet address in the second whitespace(146.149.1.0) for each one that It reports like on the above script on line 11

$ ./getobjectlst.exe -u Xxx-p Xxx -a 146.149.16.0 -o rich
"146.149.16.1" "srv114096srv" "Server" "Static" "chase.com"
"146.149.16.2" "srv114097srv" "Server" "Static" "chase.com"

For the report, I need it to be outputed as csv so I can import it into a spreadsheet, I envision it like so

( never mind on the header, I will create those in excel, but wanted to show.

Subnet Static DHCP Unused
146.149.16.0 363 0 57

I guess the output could be like this, then I will copy/paste it.
146.149.16.0,363,0,157

Then loop and do it all until its done.

Thanks for your help in advance !

This is what I have thus far, but it does not work right. I am not a perl expert so any help would be awesome !

Thanks

#!perl
 
open(my $log, ">log-subnet.txt") or die "Could not open log: $!\n";
 
##### Step 1, read subnets
open(my $in, "<m-names2.txt") or die "Could not open m-names.txt: $!\n";
while(<$in>) {
    next unless /(.*?)\/(.*)$/;
    my $subnet = $1;
    print "Checking $subnet\n";
    my @dnsoptions = `./getobjectlst.exe -u Xxx-p Xxx -a $subnet -o rich`;
    
    my %counts;
    foreach my $line (@dnsoptions) {
        my @f = split/"\s+"/, $line;
        $counts{$f[3]}++;
    }
            elsif ($line =~ /^\s*Error 48: This subnet does not exist.=([^\r\n]+)/) {
            my @subnetpart2 = `./getsubnetlst.exe -u Xxx -p Xxx -a $subnet -t netwrok -o rich`;
            my @f = split/"\s+"/, $line;
            $counts{$f[3]}++;
         }
    
 printf $log "%s,%d,%d,%d\n", $subnet, ($counts{Static} or 0), ($counts{DHCP} or 0), ($counts{Unused} or 0);
 
close($log);

Any takers want to help a brotha' out?

Maybe something like this. Please go through the script comments carefully to understand the flow of logic.

#!perl -w
my %counts;
my @subnettype;
my @dnsoptions;
my @dnsoptions2;
my @subnetpart2;
my $snetpart2;
my $subnet;
open(my $log, ">log-subnet.txt") or die "Could not open log: $!\n";
printf $log "Subnet,Static,DHCP,Unused\n";
##### Step 1, read subnets
open(my $in, "<m-names2.txt") or die "Could not open m-names2.txt: $!\n";
while(<$in>) {
  next unless /(.*?)\/(.*)$/;
  $subnet = $1;
  print "Checking $subnet\n";
  @dnsoptions = `./getobjectlst.exe -u Xxx-p Xxx -a $subnet -o rich`;
  # Now, at this point, we may have "Error 48" in @dnsoptions, or we may have
  # the nicely formatted output. We'll have to check for both cases here.
  # Let's check the unsuccessful case first. The condition below checks if
  # the first element of @dnsoptions array has the following text in it -
  # "Error 48: This subnet does not exist." in it.
  if ($dnsoptions[0] =~ /Error 48: This subnet does not exist./) {
    # call "getsubnetlst.exe", passing $subnet as one of the parameters
    @subnetpart2 = `./getsubnetlst.exe -u Xxx -p Xxx -a $subnet -t netwrok -o rich`;
    # now loop through each element of the array @subnetpart2, which looks like this - 
    # ##########################################################################
    # "East" "146.149.1.0" "N" "" "146.149.0.0" " " " " "255.255.255.128"
    # ##########################################################################
    # pick up the 2nd field from the left (e.g. 146.149.1.0 above), and pass it as
    # a parameter to the cli "getobjectlst.exe".
    foreach my $line (@subnetpart2) {
      # get the 2nd field from the left
      $snetpart2 = (split/"\s+"/, $line)[1];
      # and now pass it to "getobjectlst.exe"; assign the output to
      # the array @dnsoptions2
      @dnsoptions2 = `./getobjectlst.exe -u Xxx-p Xxx -a $snetpart2 -o rich`;
      # find out counts of each subnettype (4th field from left)
      foreach my $line (@dnsoptions2) {
        @subnettype = split/"\s+"/, $line;
        $counts{$subnettype[3]}++;
      }
    }
  } else # successful output from getobjectlst.exe
  {
    # find out counts of each subnettype (4th field from left)
    foreach my $line (@dnsoptions) {
      @subnettype = split/"\s+"/, $line;
      $counts{$subnettype[3]}++;
    }
  }
  printf $log "%s,%d,%d,%d\n", $subnet, ($counts{Static} or 0), ($counts{DHCP} or 0), ($counts{Unused} or 0);
  %counts = ();
}
close($in);
close($log);

Hope that helps,
tyler_durden

_______________________________________________________________________________________
"If you don't claim your humanity you will become a statistic. You have been warned."

HI,
Thanks for the explanation !

Will try it and let you know

Thanks a bunch !

HI,

I ran your awesome code, but I got an error:

Error 48: This subnet does not exist.
10.2.0.0
getobjectlst.exe :10.2.0.0: Error code = 48
Use of uninitialized value $dnsoptions[0] in pattern match (m//) at update-enhan.pl line 23, <$in> line 3

Hi !

I made some mods on your code, have a look, but I still get that error that the subnet does not exists.

#!perl -w
my %counts;
my @subnettype;
my @dnsoptions;
my @dnsoptions2;
my @subnetpart2;
my $snetpart2;
my $subnet;
open(my $log, ">log-external-.txt") or die "Could not open log: $!\n";
printf $log "Subnet,Static,DHCP,Unused\n";
##### Step 1, read subnets
open(my $in, "<m-names.txt") or die "Could not open m-names2.txt: $!\n";
while(<$in>) {
#next unless /(.*?)\/(.*)$/;
#next unless /(.*?)$/;
chomp;
  $subnet = $_;
  print "Checking $subnet\n";
  @dnsoptions = `./getobjectlst.exe -u xx -p xx -a $subnet -o Rich`;
  # Now, at this point, we may have "Error 48" in @dnsoptions, or we may have
  # the nicely formatted output. We'll have to check for both cases here.
  # Let's check the unsuccessful case first. The condition below checks if
  # the first element of @dnsoptions array has the following text in it -
  # "Error 48: This subnet does not exist." in it.
foreach my $line (@dnsoptions) {
            if ($line =~ /^\s*Error 48: This subnet does not exist./) {

    # call "getsubnetlst.exe", passing $subnet as one of the parameters
    @subnetpart2 = `./getsubnetlst.exe -u xx-p xx -a $subnet -t network -o Rich`;
    # now loop through each element of the array @subnetpart2, which looks like this - 
    # ##########################################################################
    # "East" "146.149.1.0" "N" "" "146.149.0.0" " " " " "255.255.255.128"
    # ##########################################################################
    # pick up the 2nd field from the left (e.g. 146.149.1.0 above), and pass it as
    # a parameter to the cli "getobjectlst.exe".


    foreach my $line (@subnetpart2) {
      # get the 2nd field from the left
      $snetpart2 = (split/"\s+"/, $line)[1];
      # and now pass it to "getobjectlst.exe"; assign the output to
      # the array @dnsoptions2
      @dnsoptions2 = `./getobjectlst.exe -u xx -p xx -a $snetpart2 -o Rich`;
      # find out counts of each subnettype (4th field from left)
    foreach my $line (@dnsoptions2) {
        @subnettype = split/"\s+"/, $line;
        $counts{$subnettype[3]}++;
      }
    }
  } else # successful output from getobjectlst.exe
  {
    # find out counts of each subnettype (4th field from left)
    foreach my $line (@dnsoptions) {
      @subnettype = split/"\s+"/, $line;
      $counts{$subnettype[3]}++;
    }
  }
  printf $log "%s,%d,%d,%d\n", $subnet, ($counts{Static} or 0), ($counts{DHCP} or 0), ($counts{Unused} or 0);
  %counts = ();
}
}
close($in);
close($log);

Do you think we need more info on this line, to match the line, looks like its calling the subnet where the error is:

foreach my $line (@dnsoptions) {
if ($line =~ /^\s*Error 48: This subnet does not exist./) {

Error 48: This subnet does not exist.
146.149.0.0/16

A couple of points here:

(1) I think the error is being thrown because the list @dnsoptions is undefined, i.e. the executable "getobjeclst.exe" probably returns a zero-length string in some cases.

(2) Again, it's quite possible that the output of "getobjectlst.exe" is something like this:



Error 48: This subnet does not exist.
146.149.0.0
getobjectlst.exe :146.149.0.0: Error code = 48

i.e. the first line could be blank. In such a case, $dnsoptions[0] would be equal to "\n". Hence a comparison like this:

  if ($dnsoptions[0] =~ /Error 48: This subnet does not exist./) {

would fail, because the string "Error 48: This subnet does not exist." is in $dnsoptions[1], or maybe in $dnsoptions[2] etc.

(3) The logic you explained is as follows:

(a) take a subnet from "m-names2.txt", and pass it to "getobjectlst.exe"
(b) if an error is thrown, pass that subnet to "getsubnetlst.exe".
(c) loop through the output of "getsubnetlst.exe", pick the 2nd token, and call "getobjectlst.exe" with that as parameter.

Now, what if "getsubnetlst.exe" itself fails, or returns a null string ? The current script does not take care of that scenario.

======================================================

For problem # (1) above, I assume you just want to iterate to the next subnet value, maybe after printing an error message.

For problem # (2) above, you'll need to see if the string "Error 48: This subnet does not exist." occurs in any element of the list @dnsoptions (and not just in $dnsoptions[0]). You could join all elements of the list into a single string, and check for the occurrence of that error message in that string.

So the modification for (1) and (2) is as follows:

  ...
  if (not defined($dnsoptions[0])) {
    print "dnsoptions is null or undefined, going on to the next subnet\n";
    next;
  }
  if (join(" ",@dnsoptions) =~ /Error 48: This subnet does not exist./) {
  ...

HTH,
tyler_durden

____________________________________________________
"Only after disaster can we be resurrected."

Hi ,

This is what the end result to your code: Unless I pasted it wrong.

I still get that dang error ( but looks a little different)

Checking 10.0.0.0/8
Checking 146.149.0.0/16
Error 48: This subnet does not exist.
146.149.0.0/16
getobjectlst.exe :146.149.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet
Checking 161.16.0.0/16
Error 48: This subnet does not exist.
161.16.0.0/16
getobjectlst.exe :161.16.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet
Checking 161.56.0.0/16

#!perl -w
my %counts;
my @subnettype;
my @dnsoptions;
my @dnsoptions2;
my @subnetpart2;
my $snetpart2;
my $subnet;
open(my $log, ">log-external-.txt") or die "Could not open log: $!\n";
printf $log "Subnet,Static,DHCP,Unused\n";
##### Step 1, read subnets
open(my $in, "<m-names.txt") or die "Could not open m-names2.txt: $!\n";
while(<$in>) {
#next unless /(.*?)\/(.*)$/;
#next unless /(.*?)$/;
chomp;
  $subnet = $_;
  print "Checking $subnet\n";
  @dnsoptions = `./getobjectlst.exe -u xx -p xx -a $subnet -o Rich`;
  # Now, at this point, we may have "Error 48" in @dnsoptions, or we may have
  # the nicely formatted output. We'll have to check for both cases here.
  # Let's check the unsuccessful case first. The condition below checks if
  # the first element of @dnsoptions array has the following text in it -
  # "Error 48: This subnet does not exist." in it.

if (not defined($dnsoptions[0])) {
    print "dnsoptions is null or undefined, going on to the next subnet\n";
    next;
  
  if (join(" ",@dnsoptions) =~ /Error 48: This subnet does not exist./) {

    # call "getsubnetlst.exe", passing $subnet as one of the parameters
    @subnetpart2 = `./getsubnetlst.exe -u xx-p xx -a $subnet -t network -o Rich`;
    # now loop through each element of the array @subnetpart2, which looks like this - 
    # ##########################################################################
    # "East" "146.149.1.0" "N" "" "146.149.0.0" " " " " "255.255.255.128"
    # ##########################################################################
    # pick up the 2nd field from the left (e.g. 146.149.1.0 above), and pass it as
    # a parameter to the cli "getobjectlst.exe".


    foreach my $line (@subnetpart2) {
      # get the 2nd field from the left
      $snetpart2 = (split/"\s+"/, $line)[1];
      # and now pass it to "getobjectlst.exe"; assign the output to
      # the array @dnsoptions2
      @dnsoptions2 = `./getobjectlst.exe -u xx -p xx -a $snetpart2 -o Rich`;
      # find out counts of each subnettype (4th field from left)
    foreach my $line (@dnsoptions2) {
        @subnettype = split/"\s+"/, $line;
        $counts{$subnettype[3]}++;
      }
    }
  } else # successful output from getobjectlst.exe
  {
    # find out counts of each subnettype (4th field from left)
    foreach my $line (@dnsoptions) {
      @subnettype = split/"\s+"/, $line;
      $counts{$subnettype[3]}++;
    }
  }
  printf $log "%s,%d,%d,%d\n", $subnet, ($counts{Static} or 0), ($counts{DHCP} or 0), ($counts{Unused} or 0);
  %counts = ();
}
}
close($in);
close($log);

What's the output of the following program ?

#!perl -w
my @dnsoptions;
my $subnet;
open(my $in, "<m-names2.txt") or die "Could not open m-names2.txt: $!\n";
while(<$in>) {
  next unless /(.*?)\/(.*)$/;
  $subnet = $1;
  print "Checking $subnet\n";
  @dnsoptions = `./getobjectlst.exe -u Xxx-p Xxx -a $subnet -o rich`;
  if (@dnsoptions) { # @dnsoptions is not empty
    if (join(" ",@dnsoptions) =~ /Error 48: This subnet does not exist./) {
      print "dnsoptions contains the Error 48.\n";
    } else {
      print "dnsoptions was created successfully, it's size = $#dnsoptions\n";
    }
  } else {
    print "dnsoptions is null or undefined, going on to the next subnet\n";
  }
}
close($in);

tyler_durden

HI, here ya go

$ perl tyler.pl
Checking 10.0.0.0
dnsoptions was created successfully, it's size = 253
Checking 146.149.0.0
Error 48: This subnet does not exist.
146.149.0.0
getobjectlst.exe :146.149.0.0: Error code = 48
dnsoptions is null or undefined, going on to the next subnet
Checking 161.16.0.0
Error 48: This subnet does not exist.
161.16.0.0
getobjectlst.exe :161.16.0.0: Error code = 48
dnsoptions is null or undefined, going on to the next subnet
Checking 161.56.0.0
Error 48: This subnet does not exist.
161.56.0.0
getobjectlst.exe :161.56.0.0: Error code = 48
dnsoptions is null or undefined, going on to the next subnet
Checking 162.2.0.0
dnsoptions is null or undefined, going on to the next subnet
Checking 162.5.0.0

HI,

This maybe a clue..

we need to retain the mask bit "/16" or what ever is set on the m-names.txt file when it calls getsubnetlst.exe

This is the code ran manually
./getsubnetlst.exe -u xx -p xx -a 146.149.0.0/16 -t network -o Rich

"East" "146.149.89.0" "Y" "" "146.149.0.0" " " " " "255.255.255.224"
"West" "146.149.89.64" "Y" "" "146.149.0.0" " " " " "255.255.255.224"
"" "146.149.90.0" "Y" "" "146.149.0.0" " " " " "255.255.255.0"
"" "146.149.91.0" "N" "" "146.149.0.0" " " " " "255.255.255.0"

The following code uses the entire line from "m-names2.txt" i.e. "167.0.0.0/8" instead of just "167.0.0.0".

#!perl -w
my @dnsoptions;
my $subnet;
open(my $in, "<m-names2.txt") or die "Could not open m-names2.txt: $!\n";
while(<$in>) {
  $subnet = $_;
  print "Checking $subnet\n";
  @dnsoptions = `./getobjectlst.exe -u Xxx-p Xxx -a $subnet -o rich`;
  if (@dnsoptions) { # @dnsoptions is not empty
    if (join(" ",@dnsoptions) =~ /Error 48: This subnet does not exist./) {
      print "dnsoptions contains the Error 48.\n";
    } else {
      print "dnsoptions was created successfully, it's size = $#dnsoptions\n";
    }
  } else {
    print "dnsoptions is null or undefined, going on to the next subnet\n";
  }
  print "====================================\n";
}
close($in);

But I think the problem lies in this line: "@dnsoptions = `./getobjectlst.exe -u Xxx-p Xxx -a $subnet -o rich`;".

It does not capture stderr of getobjectlst.exe, which is thrown out to the terminal (the text in bold red below).

Checking 146.149.0.0
Error 48: This subnet does not exist.
146.149.0.0
getobjectlst.exe :146.149.0.0: Error code = 48
dnsoptions is null or undefined, going on to the next subnet

If "getobjectlst.exe" fails, then the text in bold red does not get assigned to @dnsoptions.
But if "getobjectlst.exe" is successful, then the output does get assigned to @dnsoptions.

tyler_durden

OK, I follow you, so what do you recommend?

I ran your latest test code, this is what I got:

$ perl tyler1.pl
Checking 10.0.0.0/8

dnsoptions was created successfully, it's size = 253

Checking 146.149.0.0/16

Error 48: This subnet does not exist.
146.149.0.0/16
getobjectlst.exe :146.149.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet

Checking 161.16.0.0/16

Error 48: This subnet does not exist.
161.16.0.0/16
getobjectlst.exe :161.16.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet

Checking 161.56.0.0/16

Error 48: This subnet does not exist.
161.56.0.0/16
getobjectlst.exe :161.56.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet

Checking 162.2.0.0/16

Error 48: This subnet does not exist.
162.2.0.0/16
getobjectlst.exe :162.2.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet

Checking 162.5.0.0/16

dnsoptions was created successfully, it's size = 1021

Checking 162.15.0.0/16

Error 48: This subnet does not exist.
162.15.0.0/16
getobjectlst.exe :162.15.0.0/16: Error code = 48
dnsoptions is null or undefined, going on to the next subnet

Checking 162.30.0.0/16

One way could be to install a Perl module like IO::CaptureOutput (or others) to explicitly capture stderr as mentioned in the following webpage:

Run external process from Perl, capture stderr, stdout AND the process exit code - Stack Overflow

I haven't worked with any of the modules mentioned therein, and my current setup does not allow me to install them. I can try them later on in my personal laptop later on.

In the meantime, maybe a forum member could come up with yet another suggestion.

HTH,
tyler_durden

HI

You think thats the issue?

Yes, check this:

$
$ # the following command executes successfully
$
$ ls -1 *.jpg
file1.jpg
file2.jpg
$
$ # now when I use back-ticks to run the command,
$ # @x gets assigned the output, or "stdout" of this command
$
$ perl -e '{ @x = `ls -1 *.jpg`; }'
$
$ # it didn't print anything because I did not add the "print"
$ # command explicitly; if I do, then:
$
$ perl -e '{ @x = `ls -1 *.jpg`; print @x; }'
file1.jpg
file2.jpg
$
$ # it prints properly
$
$ # Now this command does not execute successfully
$
$ ls -1 *.bmp
ls: cannot access *.bmp: No such file or directory
$
$ # The message that you see is standard error, or "stderr"
$ # It does not get assigned to @x, as you can see below
$
$ perl -e '{ @x = `ls -1 *.bmp`; }'
ls: cannot access *.bmp: No such file or directory
$
$ # I did not add the "print" command explicitly, still I see
$ # the output - that's because it is the "stderr" thrown by
$ # the command itself. It never got assigned to @x, as the
$ # following one-liner shows.
$
$ perl -e '{ @x = `ls -1 *.bmp`; print "Value of @x => ",@x; }'
ls: cannot access *.bmp: No such file or directory
Value of  => $
$
$

So, essentially you'll have to capture the standard output (stdout) as well as the standard error (stderr) in your perl program. The "back-tick" method can capture stdout, but cannot capture stderr. That's why you'd need those additional modules mentioned in the link above.

Once you've captured both, you'd check stdout for success and stderr for failure, and proceed from there.

HTH,
tyler_durden

Hi,

I got it worked out with the help of many kind folks.

If your interested, I can post the final code?

Thanks

Sure, go ahead.

tyler_durden

Here it is.

I want to thank Durden, FishMonger, Adam and ozo

#!perl
use strict; 
use warnings; 
use Data::Dumper; 
 
open my $log, '>', 'log-external.txt' or die "Could not open log: $!"; 
print $log "Subnet,Static,DHCP,Unused\n"; 
 
open my $dump, '>', 'dump.log' or die "failed to open 'dump.log' $!"; 
 
##### Step 1, read subnets 
open my $in, '<', 'm-names.txt' or die "Could not open m-names.txt: $!\n"; 
while( my $subnet = <$in>) { 
 
    print "Checking $subnet"; 
    chomp $subnet; 
     
    my %counts = (  
                   Static => 0, 
                   DHCP   => 0, 
                   Unused => 0, 
    ); 
     
    my @dnsoptions = `./getobjectlst.exe -u xx -p xx -o rich -a $subnet 2>&1`;
 
    print $dump "dumping \@dnsoptions\n";     
    print $dump Data::Dumper->Dump(\@dnsoptions); 
    print $dump '=' x 25, "\n"; 
 
    if ( @dnsoptions and $dnsoptions[0] eq '' ) {
        print "dnsoptions is null or undefined, going on to the next subnet\n"; 
        next; 
    } 
 
    # Now, at this point, we may have "Error 48" in @dnsoptions, or we may have 
    # the nicely formatted output. We'll have to check for both cases here. 
    # Let's check the unsuccessful case first. The condition below checks if 
    # the first element of @dnsoptions array has the following text in it - 
    # "Error 48: This subnet does not exist." in it. 
 
 
    if (join("",@dnsoptions) =~ /Error 48: This subnet does not exist./) { 
 
        # call "getsubnetlst.exe", passing $subnet as one of the parameters 
        my @subnetpart2 = `./getsubnetlst.exe -u xx-p xx -o rich -a $subnet -t network`; 
 
        print $dump "dumping \@subnetpart2\n";     
        print $dump Data::Dumper->Dump(\@subnetpart2); 
        print $dump '=' x 25, "\n"; 
 
         
        # now loop through each element of the array @subnetpart2, which looks like this - 
        # ########################################################################## 
        # "East" "146.149.1.0" "N" "" "146.149.0.0" " " " " "255.255.255.128" 
        # ########################################################################## 
        # pick up the 2nd field from the left (e.g. 146.149.1.0 above), and pass it as 
        # a parameter to the cli "getobjectlst.exe". 
 
 
        foreach my $line ( @subnetpart2 ) { 
 
            # get the 2nd field from the left 
            my $snetpart2 = (split/"\s+"/, $line)[1];
             if( $snetpart2 =~ /"/ ){
             warn "\$snetpart2 was $snetpart2\n when \$line was $line";
             next;  
} 
            # and now pass it to "getobjectlst.exe"; 
            my @dnsoptions2 = `./getobjectlst.exe -u xx -p xx -o rich -a $snetpart2`;
 
            print $dump "dumping \@dnsoptions2\n";     
            print $dump Data::Dumper->Dump(\@dnsoptions2); 
            print $dump '=' x 25, "\n"; 
             
            # find out counts of each subnettype (4th field from left) 
            foreach my $line (@dnsoptions2) { 
                my @subnettype = split/"\s+"/, $line; 
                $counts{$subnettype[3]}++; 
            } 
        } 
    } 
    else { # successful output from getobjectlst.exe 
 
        # find out counts of each subnettype (4th field from left) 
        foreach my $line (@dnsoptions) { 
            my @subnettype = split/"\s+"/, $line;
            $counts{$subnettype[3]}++; 
        } 
    } 
    printf $log "%s,%d,%d,%d\n", $subnet, $counts{Static}, $counts{DHCP}, $counts{Unused}; 
} 
 
close($in); 
close($log);

Only thing I like to solve is the output format,

I would like the output from the log-external.txt
from this:

Subnet,Static,DHCP,Unused
10.0.0.0/8
,37,0,217
146.149.0.0/16

To this:

Subnet,Static,DHCP,Unused

10.0.0.0/8,37,0,217
146.149.0.0/16,174,0,39314