9 Replies - 4635 Views - Last Post: 05 April 2009 - 11:44 AM

#1 numeric  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 77
  • Joined: 12-January 09

Comparing Arrays in a while loop in perl

Posted 02 April 2009 - 09:09 AM

Hey,

I started playing about with Perl for the first time yesterday as I've got some work coming up that it will be useful for. I'm trying to write a script that will take start and end IP's for a netblock and print out all the possible IP's inbetween but I'm having a little difficulty comparing the arrays that I'm using to store the current and end IP's. Here's my code so far:

#Get the range to be displayed from the user
print "Config start address \n";
$startAddress = <STDIN>;
print "Config end address \n";
$endAddress = <STDIN>;
#Get rid of the carrage returns
chomp($startAddress);
chomp($endAddress);

#Pack the start and end address into seperate arrays to be used.
#We also need an array to store the current address.
@start = split(/\./, $startAddress);
@end = split(/\./, $endAddress);
@currentAddress = @start;

#This is the loop that I am having problems with
while(@currentAddress != @end){
	incAddress();
}

sub incAddress{
	#We don't know how big the supplied netblock will be so provide functionality for every possibility.
	printAddress();
	if ($end[3] > $currentAddress[3]){
		$currentAddress[3]++;
		printAddress();
	}
	#Increase the value of the third octet by 1 and reset the fourth octet
	if ($end[2] > $currentAddress[2] && $currentAddress[3] eq $end[3]){
		$currentAddress[2]++;
		$currentAddress[3] = 0;
		printAddress();
	}
	#Increase the value of the seccond octet by 1 and reset the third and fourth octets
	if ($end[1] > $currentAddress[1] && $currentAddress[2] eq $end[2]){
		$currentAddress[1]++;
		$currentAddress[2] = 0;
		$currentAddress[3] = 0;
		printAddress();
	}
}
sub printAddress {
	$printableAdd = join("\.", @currentAddress);
	print $printableAdd;
}



I've found a few bits and pieces on the net about comparing specific variables with in a loop but I want to check that everything is the same. Do I need to manually iterate through each element of the arrays and compare them or is there a neater way of doing it?

Thanks for any help,

-N

Is This A Good Question/Topic? 0
  • +

Replies To: Comparing Arrays in a while loop in perl

#2 bsaunders  Icon User is offline

  • D.I.C Addict

Reputation: 44
  • View blog
  • Posts: 571
  • Joined: 18-January 09

Re: Comparing Arrays in a while loop in perl

Posted 03 April 2009 - 08:40 AM

Do you know how to use the range (..) operator?
Was This Post Helpful? 0
  • +
  • -

#3 KevinADC  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 27
  • View blog
  • Posts: 401
  • Joined: 23-January 07

Re: Comparing Arrays in a while loop in perl

Posted 03 April 2009 - 10:29 AM

I would also recommend trying the range operator but getting a print out of all the possible permutations seems a bit tricky. I may and try to solve it if I have time today.
Was This Post Helpful? 0
  • +
  • -

#4 numeric  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 77
  • Joined: 12-January 09

Re: Comparing Arrays in a while loop in perl

Posted 03 April 2009 - 02:12 PM

Thanks for the replies,

This is the first time that I've heard anything about the range operator - will Google for some more info when I finish this reply.

I've been having quite the chuckle with this script over the last day or so - the output I've been getting has been random to say the least :)
Was This Post Helpful? 0
  • +
  • -

#6 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: Comparing Arrays in a while loop in perl

Posted 03 April 2009 - 02:21 PM

A couple points to consider:

1) Incrementing the address and printing it are two separate activities - printing is not a part of incrementing - so you should really be calling those two functions separately.

2) You generally want to avoid testing for (in)equality unless you have to. If $startAddress is larger than $endAddress, then the while loop as you've written it will continue forever.

3) The reason your while loop exits immediately is because the arrays are being compared in scalar context. Evaluating an array in scalar context returns the number of items in the array, so it's actually only testing whether the arrays are the same size rather than whether their contents are the same. Unfortunately, you can't compare arrays directly that way, so you have to convert them into a scalar (single-valued) representation which will also preserve relative order.

4) printAddress should take the address to print as input rather than reading the global @currentAddress directly. Aside from keeping things generally cleaner, this would give you the option of having it print @start or @end instead of @currentAddress. You also don't really need to use $printableAdd; you can print the join directly.

5) Think of the IP address as a four-digit, base 256 number. When you're counting up, you need to increment the last octet all the way to 255, then reset it to 0 and increase the second-to-last octet (until it reaches 255), etc. Your current incAddress routine increments each octet individually without going through the entire range. Unless you're doing a class C or smaller subnet (i.e., the first three octets of the start and end addresses are the same), the incrementing algorithm you're using will produce incorrect results.

So, given #1, #2, and #3, your main loop should be:
while (sprintf('%3d%3d%3d%3d', @currentAddress) lt
	   sprintf('%3d%3d%3d%3d', @end)) {
  printAddress(@currentAddress);
  incAddress();
}
printAddress(@currentAddress);


For #4, revise printAddress to:
sub printAddress {
  # @_ holds the parameters passed to the sub
  print join(".", @_), "\n";
}


As for #5, incAddress needs to take a completely different approach to produce consistently correct results, so I'll give you a chance to try rewriting it using that approach first before posting a working version.

And, as a final note, pretty much all Perl code should start with
use strict;
use warnings;
if you have any interest in keeping it maintainable. This will require you to declare all variables with "my" the first time they're used (e.g., "my $startAddress = <STDIN>;"), but should introduce few other complications. In exchange, strict and warnings will help to protect you from a wide range of common errors or sloppy habits which will come back to haunt you.
Was This Post Helpful? 1
  • +
  • -

#7 castaway  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 5
  • Joined: 04-April 09

Re: Comparing Arrays in a while loop in perl

Posted 04 April 2009 - 11:07 AM

Hi numeric,

Are you doing this for education or real use? If you actually want to use the result, may I suggest you use a pre-made solution.

Install http://search.cpan.org/dist/Net-IP, then you can do:

  use Net::IP;
  my $ip = Net::IP->new($startAddress - $endAddress) || die;
  # Loop
  do {
	  print $ip->ip(), "\n";
  } while (++$ip);



And your code is done.

Jess
Was This Post Helpful? 1
  • +
  • -

#8 numeric  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 77
  • Joined: 12-January 09

Re: Comparing Arrays in a while loop in perl

Posted 04 April 2009 - 03:12 PM

@dsherohman: Great post! Thanks for taking the time to look over the rest of the code as well. I'll start rewriting the code to include your suggestions as soon a I get a bit of time to do so.

@castaway: I came up with the idea for the script as a way of learning a bit more about how to use Perl in a practical setting - the script would have to take subnet masks into account to be of any use in a real world setting.

I've been having a little trouble finding more in depth information about perl - I've found plenty of information about syntax and the very basic's (although none so far that have included the use statements that dsherohman was kind enough to point out) but little on using modules and even less about OOP in Perl. If anyone could point to some better resources I would be grateful.

Cheers,

-n
Was This Post Helpful? 0
  • +
  • -

#9 castaway  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 5
  • Joined: 04-April 09

Re: Comparing Arrays in a while loop in perl

Posted 04 April 2009 - 03:52 PM

Theres a whole section on "Getting started" here: http://www.perlmonks...?node=Tutorials

Try that, also the perlmonks website is a good place to ask more questions.

Jess
Was This Post Helpful? 0
  • +
  • -

#10 dsherohman  Icon User is offline

  • Perl Parson
  • member icon

Reputation: 226
  • View blog
  • Posts: 654
  • Joined: 29-March 09

Re: Comparing Arrays in a while loop in perl

Posted 05 April 2009 - 10:52 AM

View Postcastaway, on 4 Apr, 2009 - 10:52 PM, said:

Theres a whole section on "Getting started" here: http://www.perlmonks...?node=Tutorials

Try that, also the perlmonks website is a good place to ask more questions.

Jess


Seconded. PerlMonks.org is the site for Perl information.
Was This Post Helpful? 0
  • +
  • -

#11 KevinADC  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 27
  • View blog
  • Posts: 401
  • Joined: 23-January 07

Re: Comparing Arrays in a while loop in perl

Posted 05 April 2009 - 11:44 AM

I agree perlmonks is probably the the best perl site on the net, especially for Q&A. I recommend it but caution that some of the stuff is quite old and possibly using deprecated functions/syntax or just out of date entirely. I recommend getting the latest version of "Perl Bookshelf Reference" on CD which comes with several perl books and should be up to date. Used copies are only a few dollars.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1