CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Advanced:
FOR LOOP HELP

 



phone4u
Novice

Jul 31, 2010, 1:28 PM

Post #1 of 11 (4891 views)
FOR LOOP HELP Can't Post

Hi, I need urgent help in writing a for-loop for a perl script below;
Code

#!/usr/bin/perl
use Net::IPTrie;
my $tr = Net::IPTrie->new(version=>6); # IPv6

$tr->add(address=>'2a02:ee0::/32', prefix=>64, data=>'43333');
$tr->add(address=>'2a02:e98::/32', prefix=>64, data=>'24641');

my $a = $tr->add(address=>'2a02:ee0::2', data=>$data); # prefix defaults to 32
print "\$a is ". $a->address . " and parent of \$a is ". $a->parent->address ." and data of parents is: ". $a->parent->data. "\n";


die;


The part with $tr->add(address=>'2a02:.........); is saved in a file lexo.txt becos they are a lot of addresses to be added, also part with with my $a =$tr->add(address=>'2a02:.......); saved in another file which contains a lot addresses to be added too.
So I need help with for loop that will run through each saved .txt files. Thanks


deepeshtronics
Novice

Aug 1, 2010, 3:18 AM

Post #2 of 11 (4870 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Hi,

You have two text files, right?
I suppose you want to go through the content of text files on line-by-line basis.
Use the following code to do this.

#!/usr/perl/bin
use warnings;
use strict;

my @text_files = @ARGV;
for (@text_files) {
read_text_file($_) if $_;
}
sub read_text_file {
my $file = shift;
open INPUT, $file or die "Can't open file: $!\n";
while (<INPUT>) {
print "$_";
}
close INPUT;
}

Usage:
perl script.pl 1.txt 2.txt

Let me know if your requirement is something else.

Thanks


phone4u
Novice

Aug 1, 2010, 7:51 AM

Post #3 of 11 (4858 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Thanks for your urgent response, but i didnt seem to get it working. For the first text, it was saved as lexo.txt and I want it to replace;
$tr->add(address=>'2a02:ee0::/32', prefix=>64, data=>'43333');
$tr->add(address=>'2a02:e98::/32', prefix=>64, data=>'24641'); as I have thousands of them saved in file lexo.txt already.
And for this line; my $a = $tr->add(address=>'2a02:ee0::2', data=>$data); I have all the IPv6 (2a02:ee0::2)saved in a text file called IPv6.txt, I want the script to read each v6 addresses from IPv6.txt to perform the function following it.
I hope you have an idea of what I intend doing now, I am a beginner in perl and i will appreciate if you can help me out by putting the file-names to the script. So that it will look like;

#!/usr/bin/perl
use Net::IPTrie;
my $tr = Net::IPTrie->new(version=>6); # IPv6

"the new line of script reading from lexo.txt"

"the new line of script reading different IPv6 addresses from IPv6"
print "\$a is ". $a->address . " and parent of \$a is ". $a->parent->address ." and data of parents is: ". $a->parent->data. "\n";


die;
Thank you very much for your anticipated help.


deepeshtronics
Novice

Aug 1, 2010, 11:19 AM

Post #4 of 11 (4851 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Hi,

I really need some more inputs from your end.

Provide 2 or 3 lines of sample text from lexo.txt.
Provide 2 or 3 lines of sample text from IPv6.txt.
Provide the expected output (i mean $a=) for these lines.

My understanding->
$tr->add(address=>'2a02:ee0::/32', prefix=>64, data=>'43333');
From above line $data = 43333;
$a = $tr->add(address=>'2a02:ee0::2', data=>$data);
In above line value of address you will pick from IPv6.txt

Is there for each line in lexo.txt, a corresponding line in IPv6.txt.

Do we have to go through line by line in both files or for each line of lexo.txt we have go through whole IPv6.txt file line-by-line?

Kindly provide more details with example if possible.

Thanks


phone4u
Novice

Aug 1, 2010, 1:51 PM

Post #5 of 11 (4847 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

here is content of lexo.txt;
$tr->add(address=>'2a02:e20::/32', prefix=>'64', data=>'29276');
$tr->add(address=>'2a02:e28::/48', prefix=>'64', data=>'41696');
$tr->add(address=>'2a02:e48::/32', prefix=>'64', data=>'5379');
$tr->add(address=>'2a02:e70::/32', prefix=>'64', data=>'33965');
$tr->add(address=>'2a02:e78::/32', prefix=>'64', data=>'48259');
$tr->add(address=>'2a02:e78::/33', prefix=>'64', data=>'48259');
$tr->add(address=>'2a02:e8::/32', prefix=>'64', data=>'43128');
$tr->add(address=>'2a02:e98::/32', prefix=>'64', data=>'24641');
$tr->add(address=>'2a02:ed0::/32', prefix=>'64', data=>'47956');
$tr->add(address=>'2a02:ee0::/32', prefix=>'64', data=>'43333');
$tr->add(address=>'2a02:ee8::/32', prefix=>'64', data=>'35574');
$tr->add(address=>'2a02:ef0::/32', prefix=>'64', data=>'39242');
$tr->add(address=>'2a02:ef8::/32', prefix=>'64', data=>'49026');
$tr->add(address=>'2a02:f08::/32', prefix=>'64', data=>'42184');

and here's content of IPv6.txt;
2001:1250::12
2001:12f0:300:1::151
2001:12f0:300:1::132
2001:12ff:0:2::3
2001:12ff:0:4::22
2001:12ff::1
2001:12ff:0:2::3
2001:12ff:0:4::22
2001:13c7:7001:4000::3
2001:13c7:7002:4000::10
2001:1400::1
2001:1418:100:1b5::2
2001:1418:100:1cf::2
2001:1418:100:22::2
2001:1418:100:359::2
2001:1418:100:d4::2
2001:1418:10:5::2
The Perl script aim is to do a look-up from lexo.txt trie, so for each line in IPv6.text the script will check which prefix and AS number they belong to according to trie added from lexo.txt.
If everything is ok, the script should print corresponding prefix and AS from lexo.txt for each IP addresses in IPv6.txt

Thanks


deepeshtronics
Novice

Aug 2, 2010, 12:00 PM

Post #6 of 11 (4803 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Hi,

I have never used the module "Net::IPTrie" but i suppose that following code should serve you purpose.

My understanding for your problem goes as follows.

That lexo.txt contains the base address of ips (from IPv6.txt). I mean it contains the class. Now you first want to identify the class (from lexo.txt) for an ip (from IPv6.txt) then you want to fetch the prefix and AS from the class.


Code
#!/usr/bin/perl 

use warnings;
use strict;

use Net::IPTrie;
my $tr = Net::IPTrie->new(version=>6); # IPv6

open LEXO, "<", "lexo.txt" or die "Could not open file lexo.txt in read mode: $!\n";
open IPV6, "<", "IPv6.txt" or die "Could not open file IPv6.txt in read mode: $!\n";

my @lexo_content = <LEXO>;
my @ipv6_content = <IPV6>;

foreach my $ip (@ipv6_content) {
chomp $ip;
foreach my $line (@lexo_content) {
chomp $line;
if($line =~ m/prefix=>\'(.*?)\',\s*data=>\'(.*?)\'/){
my $prefix = $1;
my $data = $2;
my $address = $tr->add(address=>"$ip", prefix=>"$prefix", data=>"$data");
if ($address->parent->address eq $line->address) {
print "ip::[$ip]\nprefix::[$prefix]\ndata::[$data]\n";
}
}
}
}

close LEXO;
close IPV6;


If below code does not work then apply some matching patterns through regular expressions and do your job. I am not sure that $address->parent will work.


Code
if ($address->parent->address eq $line->address) { 
print "ip::[$ip]\nprefix::[$prefix]\ndata::[$data]\n";
}


Reply if you still face problem.

Thanks


phone4u
Novice

Aug 3, 2010, 5:42 AM

Post #7 of 11 (4787 views)
Re: [deepeshtronics] FOR LOOP HELP [In reply to] Can't Post

hi thanks a lot for your, it doesn't seem to work but I decided to paste the file lexo this way and try to use the for-loop to read the IPV6.txt , but each time the IP isn't available on the lexo list, it stops and give this error;

"Can't call method "address" on an undefined value at b.pl line 3204, <IPV6> line 4428."

Now, I hope you can help me with additional script that will ignore this error and continue with other IPs in the list till it reach the end.

Here is what have done so far;

#!/usr/bin/perl
use Net::IPTrie;
my $tr = Net::IPTrie->new(version=>6); # IPv6

$tr->add(address=>'2001:1200::/32', prefix=>'64', data=>'16531');
$tr->add(address=>'2001:1210::/32', prefix=>'64', data=>'2549');
$tr->add(address=>'2001:1218::/32', prefix=>'64', data=>'278');
$tr->add(address=>'2001:1228::/32', prefix=>'64', data=>'18592');
$tr->add(address=>'2001:1250::/32', prefix=>'64', data=>'28497');
$tr->add(address=>'2001:1258::/32', prefix=>'64', data=>'28499');
$tr->add(address=>'2001:1284::/32', prefix=>'64', data=>'14868');
$tr->add(address=>'2001:1291::/32', prefix=>'64', data=>'16735');
$tr->add(address=>'2001:1298::/32', prefix=>'64', data=>'28296');
$tr->add(address=>'2001:129c::/32', prefix=>'64', data=>'22356');
$tr->add(address=>'2001:12a4::/32', prefix=>'64', data=>'28346');
$tr->add(address=>'2001:12b0::/32', prefix=>'64', data=>'28618');
$tr->add(address=>'2001:12c0::/32', prefix=>'64', data=>'11706');
$tr->add(address=>'2001:12c4::/32', prefix=>'64', data=>'28262');
$tr->add(address=>'2001:12c8::/32', prefix=>'64', data=>'21911');


open IPV6, "<", "IPV6.txt" or die "Could not open file IPv6.txt in read mode: $!\n";
my @ipv6_content = <IPV6>;

foreach my $line (@ipv6_content) {
chomp $line;

my $a = $tr->add(address=>"$line", data=>$data); # prefix defaults to 32
print "\$a is ". $a->address . " and parent of \$a is ". $a->parent->address ." and data of parents is: ". $a->parent->data. "\n";

}
close IPV6;


Code



      
    


deepeshtronics
Novice

Aug 3, 2010, 9:47 AM

Post #8 of 11 (4772 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Hi,

I installed module "Net::IPTrie" in my machine and tested the code after doing some modifications. It seems that code is working fine.

Please use below code.


Code
#!/usr/bin/perl 

use warnings;
use strict;

use Net::IPTrie;
my $tr = Net::IPTrie->new(version=>6); # IPv6

open LEXO, "<", "lexo.txt" or die "Could not open file lexo.txt in read mode: $!\n";
open IPV6, "<", "IPv6.txt" or die "Could not open file IPv6.txt in read mode: $!\n";

my @lexo_content = <LEXO>;
my @ipv6_content = <IPV6>;

foreach my $ip (@ipv6_content) {
chomp $ip;
foreach my $line (@lexo_content) {
chomp $line;
if($line =~ m/address=>\'(.*?)\',\s*prefix=>\'(.*?)\',\s*data=>\'(.*?)\'/){
my $address = $1;
my $prefix = $2;
my $data = $3;
my $n = $tr->add(address=>"$address", prefix=>"$prefix", data=>"$data");
my $a = $tr->add(address=>"$ip", prefix=>'128', data=>"$data");;
if ($a->parent->address eq $n->address) {
print "\$a is ". $a->address . " and parent of \$a is ". $a->parent->address ." and data of parents is: ". $a->parent->data. "\n";
}
}
}
}

close LEXO;
close IPV6;


Input lexo.txt:

Quote
$tr->add(address=>'2001:1200::/32', prefix=>'64', data=>'16531');
$tr->add(address=>'2001:1210::/32', prefix=>'64', data=>'2549');
$tr->add(address=>'2001:1218::/32', prefix=>'64', data=>'278');

Input IPv6.txt:

Quote
2001:1200::1
2001:1218::3


OUTPUT

Quote
$a is 2001:1200::1 and parent of $a is 2001:1200::/32 and data of parents is: 16531
$a is 2001:1218::3 and parent of $a is 2001:1218::/32 and data of parents is: 278


I hope this serves your purpose.

Go through the code and test it properly. If now, some modification is needed on the basis of input patterns in the lexo.txt and IPv6.txt, I expect that from you.

Thanks


(This post was edited by deepeshtronics on Aug 3, 2010, 9:50 AM)


phone4u
Novice

Aug 3, 2010, 12:28 PM

Post #9 of 11 (4760 views)
Re: [deepeshtronics] FOR LOOP HELP [In reply to] Can't Post

You are indeed a saviour, thanks a lot for your help.......it works perfectly now but only for some certain IPs like the one you listed, while some other IPs on the list aint working but I guess i need to update the prefix list(lexo.txt), in the mean time, I wish the script can ignore this error(Can't call method "address" on an undefined value at guru.pl line 23, <IPV6> line 4428.) and continue with other IPs that will work till the end of the list.

I really appreciate your time and help,thanks a million.


phone4u
Novice

Aug 6, 2010, 4:26 AM

Post #10 of 11 (4567 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Hi, Thanks for all your help, please I need one last help pleaseeeeee.
Please, I want the script to save file lexo.txt in the memory of this script and the file IPv6.txt will read only from that memory.
At the present, I discovered that the content of file IPv6.txt is reading through lexo.txt from the begining each time which takes longer time like days. Its suppose to take all the files in IPv6.txt once to read through lexo.txt and all the output appears in few seconds.
here is what have done so far;
#!/usr/bin/perl

use warnings;
use strict;

use Net::IPTrie;
my $tr = Net::IPTrie->new(version=>6); # IPv6

open LEXO, "<", "lexo.txt" or die "Could not open file lexo.txt in read mode: $!\n";
open IPV6, "<", "IPv6.txt" or die "Could not open file IPv6.txt in read mode: $!\n";

my @lexo_content = <LEXO>;
my @ipv6_content = <IPV6>;

foreach my $ip (@ipv6_content) {
chomp $ip;
foreach my $line (@lexo_content) { ........think the problem is here
chomp $line; ..............think the problem is here
if($line =~ m/address=>\'(.*?)\',\s*prefix=>\'(.*?)\',\s*data=>\'(.*?)\'/){
my $address = $1;
my $prefix = $2;
my $data = $3;
my $n = $tr->add(address=>"$address", prefix=>"$prefix", data=>"$data");
my $a = $tr->add(address=>"$ip", prefix=>'128', data=>"$data");;
if (defined $a->parent && $a->parent->address eq $n->address) {
print "\$a is ". $a->address . " and parent of \$a is ". $a->parent->address ." and data of parents is: ". $a->parent->data. "\n";
}
}
}
}

close LEXO;
close IPV6;


Thanks


1arryb
User

Aug 24, 2010, 10:31 AM

Post #11 of 11 (4292 views)
Re: [phone4u] FOR LOOP HELP [In reply to] Can't Post

Hi phone,


Quote
I want the script to save file lexo.txt in the memory of this script and the file IPv6.txt will read only from that memory.

I do not understand this comment. You already read lexo.txt to an array here:

Code
my @lexo_content = <LEXO>;

so that is not the problem.

What is a problem is that the Big O of this program is 2, and the regular expression is inside the inner loop.
That means you are doing <number of lines in ipv6.tx> x <number of lines in lexo.txt> regular expressions.
You haven't noted them, but this program makesTWICE as many calls to $tr->add() as it does regular expressions!
I'm sure that's significant.

The first thing to try is to break up the regular expressions to reduce their complexity and obviate the unnecessary ones.

Instead of:

Code
if($line =~ m/address=>\'(.*?)\',\s*prefix=>\'(.*?)\',\s*data=>\'(.*?)\'/){  
...
}

You could try testing for a likely line to parse using a much simpler (and faster) expression:

Code
# Notes: '^' anchors the expression at line start, simplifying the line scan. 
# 'o' precompiles the regex so it executes faster on the 2nd and succeeding iteration.
if ( $line =~ /^address=>/o ) {
$line =~ /^address=>\'(.*?)\',\s*prefix=>\'(.*?)\',\s*data=>\'(.*?)\'/)/o;
...
}

By refactoring, we can drastically reduce the number of both regular expressions and $tr->add calls.

If you pre-parse lexo.txt into a hash keyed by ip you reduce the number of regular expressions to <number of lexo.txt lines>
and reduce the number of $tr->add() calls to <number of lexo.txt lines> + <number of ipv6.tx lines>:

Code
 
# Warning: untested, snippet.

my $lexo_hash = {};
foreach my $line (@lexo_content) {
chomp($line);
$line =~ /^address=>\'(.*?)\',\s*prefix=>\'(.*?)\',\s*data=>\'(.*?)\'/)/o;
next unless ( defined($1) and defined($2) and defined($3) );
my $n = $tr->add(address=>"$1", prefix=>"$2", data=>$3);
# Not sure if we're allowed to cache Net::Trie thingies, so convert to a hash.
$lexo_hash->{$n->{address}} = { address => $n->address, prefix => $n->prefix, data => $n->data };
}

foreach my $ip ( $ipv6_content ) {
chomp($ip);
my $a = $tr->add(address=>"$ip", prefix=>"128", data=>'blah'); # Assumes $a->data isn't significant.
next unless defined( $a->parent );
next unless exists($lexo_hash->{$a->parent->address});
print "\$a is ". $a->address . " and parent of \$a is "
. $a->parent->address . " and data of parents is: "
. $lexo_hash->{$a->parent->address}->{data} . "\n";
}


I hope this helps.

Cheers,

Larry


(This post was edited by 1arryb on Aug 24, 2010, 10:50 AM)

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives