The code below returns me nothing.

F

Facco Eloelo

I find NetAddr::IP is good.
But the code below returns me nothing.
can some body help me? thx.


#!/usr/bin/perl
use NetAddr::IP;

my $list_file = 'IPlist.txt';
my $segment_file = 'IPsegment.txt';
my $match_file = 'match.txt';

open my $IPsegment, '<', $segment_file or die "Cannot open $in_file: $!";
open my $IPlist, '<', $list_file or die "Cannot open $in_file: $!";
open my $IPmatch, '>', $match_file or die "Cannot open $out_file: $!";

while ( <$IPsegment> ) {
chomp;
$segment=$_;
my $space = NetAddr::IP->new($segment);

while ( <$IPlist> ) {
chomp ($_);
($domain, $domip) = split(/,/, $_);
for my $ip (map {NetAddr::IP->new($_) } $domip)
{
print my $IPmatch $domain,$ip, "\n"
if $space->contains($ip);
}
}
}


--
 
M

Mladen Gogala

($domain, $domip) = split(/,/, $_);
for my $ip (map {NetAddr::IP->new($_) } $domip)

That "map" is incorrectly applied. Map works on lists and $domip is
a scalar variable, and consequently, map function doesn't do
anything. If you pushed your IP addresses into an array and applied
map function to the array, it would work better. Here is what the fine
manual says:
map BLOCK LIST
map EXPR,LIST
Evaluates the BLOCK or EXPR for each element of LIST (locally
setting $_ to each element) and returns the list value composed
of the results of each such evaluation. In scalar context,
returns the total number of elements so generated. Evaluates
BLOCK or EXPR in list context, so each element of LIST may pro-
duce zero, one, or more elements in the returned value.


Notice the word "LIST", printed in capitals. Scalar is not a list.
 
F

Facco Eloelo

Still have some problem :-(

#!/usr/bin/perl
use NetAddr::IP;
use warnings;

my $list_file = 'IPlist.txt';
my $segment_file = 'IPsegment.txt';
my $match_file = 'match.txt';

open my $IPsegment, '<', $segment_file or die "Cannot open $segment_file: $!";
open my $IPlist, '<', $list_file or die "Cannot open $list_file: $!";
open my $IPmatch, '>', $match_file or die "Cannot open $match_file: $!";

@line=<$IPsegment>;
$num = @line;
for($i=0;$i<$num;$i++)
{
my $space = NetAddr::IP->new($line[$i]);

for my $ip (map { NetAddr::IP->new($_) } <$IPlist>)
{
print $ip, "\n"
if $space->contains($ip);
}
}
--
 
U

Uri Guttman

MG> That "map" is incorrectly applied. Map works on lists and $domip is
MG> a scalar variable, and consequently, map function doesn't do
MG> anything. If you pushed your IP addresses into an array and applied
MG> map function to the array, it would work better. Here is what the fine
MG> manual says:
MG> map BLOCK LIST
MG> map EXPR,LIST

MG> Notice the word "LIST", printed in capitals. Scalar is not a list.

that is wrong. a single value is just a list with one element. there is
no problem with using map (nor any other func that takes a list) on a
single scalar. ever try push @foo, $bar? works fine and it too takes a
list as its second argument.

so the OP's problem lies elsewhere.

uri
 
A

Anno Siegel

Mladen Gogala said:
That "map" is incorrectly applied.

It doesn't make much sense, but the map application is valid.
Map works on lists and $domip is
a scalar variable, and consequently, map function doesn't do
anything.

Not true. When the syntax requires a LIST, any mixture of scalars,
arrays (and even hashes) can be given. They will all be flattened
into one list.
If you pushed your IP addresses into an array and applied
map function to the array, it would work better.

That's not necessary. A special case of the above is

map NetAddr::IP->new($_), $domip;

That will execute and return NetAddr::IP->new($domip). "map" is
unnecessary, but it works.
Here is what the fine
manual says:


map BLOCK LIST
map EXPR,LIST
Evaluates the BLOCK or EXPR for each element of LIST (locally
setting $_ to each element) and returns the list value composed
of the results of each such evaluation. In scalar context,
returns the total number of elements so generated. Evaluates
BLOCK or EXPR in list context, so each element of LIST may pro-
duce zero, one, or more elements in the returned value.


Notice the word "LIST", printed in capitals. Scalar is not a list.

Sometimes it is.

Anno
 
A

Anno Siegel

Facco Eloelo said:
I find NetAddr::IP is good.
But the code below returns me nothing.
can some body help me? thx.


#!/usr/bin/perl
use NetAddr::IP;

my $list_file = 'IPlist.txt';
my $segment_file = 'IPsegment.txt';
my $match_file = 'match.txt';

open my $IPsegment, '<', $segment_file or die "Cannot open $in_file: $!";
open my $IPlist, '<', $list_file or die "Cannot open $in_file: $!";
open my $IPmatch, '>', $match_file or die "Cannot open $out_file: $!";

while ( <$IPsegment> ) {
chomp;
$segment=$_;
my $space = NetAddr::IP->new($segment);

while ( <$IPlist> ) {

You are trying to read the same file repeatedly in a loop. After the
first time through, the file will be positioned at eof and stay there.
You need to rewind the file (see perldoc -f seek).

A better solution would probably be to read $IPlist once and store
the contents in a data structure. A hash keyed on $ip looks reasonable.

[snip]

Anno
 
A

Anno Siegel

Bill Segraves said:
<snip>

FYI, the OP is trying to adapt the code example (which works fine here) for
"Matching against your address space" at
http://mipagina.cantv.net/lem/perl/iptut.htm to his particular problem.

It runs? It contains a trivial but fatal error, twice. After correction
it does work as expected. It also made clearer to me what the purpose
of the code is.

So the OP is trying to match the same list of IP's (from some file,
that part is snipped) against a series of IP spaces (from another file).

So first read the list of addresses. Assuming each line is ready for
consumption by NetAddr::IP (which may not be true):

my @addrs;
while ( <$addrs> ) {
chomp;
push @addrs, NetAddr::IP->new($_);
}

Now read each range in sequence and check all addresses against each
one:

while ( <$spaces> ) {
chomp;
my $space = NetAddr::IP->new( $_);
for ( @addrs ) {
if ( $space->contains( $_) ) {
# report match
}
}
}

The same method could be applied with the roles of $addrs and $spaces
reversed: Read all spaces into a list, then apply them to each address
as it is read. If the list of addresses is huge, but the list of spaces
isn't, that may be preferable. Both methods report the same matches,
but in a different sequence.

Anno
 
U

Uri Guttman

MG> I stand corrected. It is syntactically corect, but doesn't make
MG> much sense.

passing a single scalar to map does make sense in some circumstances. i
use it to alias a scalar to $_ when i have code that must act on
$_. check out Sort::Maker for a case like that where i generate map code
on scalar values.

uri
 
M

Mladen Gogala

passing a single scalar to map does make sense in some circumstances. i
use it to alias a scalar to $_ when i have code that must act on
$_. check out Sort::Maker for a case like that where i generate map code
on scalar values.

Wow! Thanks Uri, you're really a master! I don't consider myself
a perl guru, as a matter of fact, I'm rather far from it, and I'm
grateful for anything that I can learn.
 
A

Anno Siegel

Bill Segraves said:
Hmm, Anno, I'm not sure what you mean by "It". I was referring to the code
at the above link, to which I had referred the OP. I just checked it again.
Runs fine here. If you are aware of errors in the example I cited at
http://mipagina.cantv.net/lem/perl/iptut.htm, perhaps you could point them
out, especially for the benefit of the OP.

Yes, I mean the code under "Matching against your address space" on
http://mipagina.cantv.net/lem/perl/iptut.htm. It goes:

use NetAddr::IP;

my $space = new NetAddr::IP->new('10.128.0.0/17');

for my $ip (map { new NetAddr::IP->new($_) } <DATA>)
{
print $ip, "\n"
if $space->contains($ip);
}

__DATA__
172.16.1.1
172.16.1.5
...


There's a "new" too many in "new NetAddr::IP->new( ...);". I suppose the
call was originally in indirect object syntax and was re-written to use
arrow notation. Now it contains both :)

As I said, it's a trivial error and easily corrected.

Anno
 
E

Eric Bohlman

passing a single scalar to map does make sense in some circumstances. i
use it to alias a scalar to $_ when i have code that must act on
$_. check out Sort::Maker for a case like that where i generate map code
on scalar values.

What advantage does that have over the more traditional use of for() for
that purpose?
 
A

Anno Siegel

Bill Segraves said:
You've a sharp eye, Anno. Thanks for the clarification. I'll point out the
error(s) to the author of NetAddr::IP.


I was a bit befuddled when you wrote (earlier that) the errors were "fatal",
as they certainly weren't fatal on this Win32 with (Indigo) Perl 5.6.1
workstation. That said (written), I've corrected the errors on my copy of
the script.

It wasn't my sharp eye but a run time error that alerted me to the bug.

When I call "new NetAddr::IP->new('10.128.0.0/17')", I get to see "Can't
call method "new" on an undefined value...". The call translates to
"'NetAddr::IP'->new->new('10.128.0.0/17')" (Deparse), and since new()
without arguments returns undef, I can't see how it would ever
work. So what I see is a fatal error.

Anno
 
A

Anno Siegel

Brian McCauley said:
Bill Segraves said:
It runs? It contains a trivial but fatal error, twice.

Hmm, Anno, I'm not sure what you mean by "It". I was referring to the code
at the above link, to which I had referred the OP. I just checked it again.
Runs fine here.

Yes, I mean the code [...] It goes:

my $space = new NetAddr::IP->new('10.128.0.0/17');

There's a "new" too many in "new NetAddr::IP->new( ...);". I suppose the
call was originally in indirect object syntax and was re-written to use
arrow notation. Now it contains both :)

But, of course, that's not fatal. It first calls new() as a class
method and constructs an object, then it calls new() as an instance
method (probably meaningless).

But NetAddr::IP->new() returns undef (experimentally), so the object
method call doesn't happen. It could work, but in the given case it
doesn't.

Anno
 
A

Anno Siegel

Eric Bohlman said:
What advantage does that have over the more traditional use of for() for
that purpose?

I agree that one-shot "for" is more frequently seen, but map has
different properties that may be advantages.

One is the usual difference between map and for. Map returns a value,
the statement in for must have a side effect. That's the same, whether
you use the one-shot form or a real loop.

Another difference is that map isn't a statement modifier, so you
can combine it with variable declarations.

my ( $y) = map ..., $x;

is fine, but this is disallowed:

my $y = ... for $x;

Anno
 
A

Anno Siegel

Bill Segraves said:
Interesting! What OS and Perl versions are you running? I see you're using
trn for news; but I don't know the environment in which you experienced the
run-time errors. I'll run the same script that works fine on this Win32
workstation on the same workstation running Linux to see what *I* see, if
you're interested.

Situation here is Darwin 7.4.0, Perl 5.8.5, NetAddr::IP 3.20.

A glance at NetAddr::IP shows that new() is prepared to be called as an
object method, so if the call without an argument happens to return
an actual object on a system, that would make it appear to work.

Otherwise, what I see at a glance doesn't make me too happy. The
new() method has a prototype. There *may* be a good reason for that,
but I doubt it. I'm afraid the author wasn't aware that prototypes
have no effect on methods.

The next few lines contain this sequence:

my $ip = lc $_[1];
# ...
$ip = 'default' unless defined $ip;

Well, it's too late to check $ip for undef. This doesn't build trust in
the code.

Mind you, there can still be a lot of useful knowledge and functionality
in the module, but I wouldn't be the least surprised if it showed
irregular behavior under unusual circumstances.

Anno
 
U

Uri Guttman

MG> Wow! Thanks Uri, you're really a master! I don't consider myself
MG> a perl guru, as a matter of fact, I'm rather far from it, and I'm
MG> grateful for anything that I can learn.

then send your praise to damian conway for that little tidbit as i got
the idea from him. :)

uri
 
U

Uri Guttman

EB> What advantage does that have over the more traditional use of for() for
EB> that purpose?

i needed the result of getting stuff FROM $_ and but not modifying
it. the extract code you pass into Sort::Maker::make_sorter works on $_
and i needed a simple way to alias the full record to $_ and map was the
right trick. look at the code to see how i used it to do that.

uri
 
E

eloelo

Anno said:
The same method could be applied with the roles of $addrs and $spaces
reversed: Read all spaces into a list, then apply them to each address
as it is read. If the list of addresses is huge, but the list of spaces
isn't, that may be preferable. Both methods report the same matches,
but in a different sequence.


why these code below can run only once.
#!/usr/bin/perl
use NetAddr::IP;

open(D2,"IPlist");

open(D3,"IPsegment");
@line=<D3>;
$num=@line;

for($i=0;$i<$num;$i++)
{
$segment= $line[$i];
my $space = NetAddr::IP->new($segment);

for my $ip (map {NetAddr::IP->new($_) } <D2>)
{
print $ip, "\n"
if $space->contains($ip);
}
}


IPlist
62.111.0.29
207.12.133.45
207.12.133.46

IPsegment
62.111.0.0/16
207.12.0.0/16

result
62.111.0.29

it means the "for"(the external one) loop run only once,why?
 
A

Anno Siegel

Abigail said:
Anno Siegel ([email protected]) wrote on MMMCMLXXXVII
September MCMXCIII in <URL:))
)) Another difference is that map isn't a statement modifier, so you
)) can combine it with variable declarations.
))
)) my ( $y) = map ..., $x;
))
)) is fine, but this is disallowed:
))
)) my $y = ... for $x;


Well, that's not disallowed (yet) - but it's behaviour is certainly not "DWIM".

Well, discouraged. From perlsyn:

NOTE: The behaviour of a "my" statement modified with a statement modi-
fier conditional or loop construct (e.g. "my $x if ...") is undefined.
The value of the "my" variable may be "undef", any previously assigned
value, or possibly anything else. Don't rely on it. Future versions
of perl might do something different from the version of perl you try
it out on. Here be dragons.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top