0
\$\begingroup\$

I have two arrays:

  • first one is ip addresses from billing for blocking
  • second is ip addresses from firewall - already blocked

My task is, compare it, and if ip address new in billing list - block it (run a command) if ip address not in billing list unblock it.

Current solutions is:

#billing->router
foreach $ip (@ipfw_ip) {
 if ( grep $_ eq $ip, @bill_ip ) {
 } else {
 `/sbin/ipfw table 11 add $ip`;
 print "$ip blocked\n";
 }
}
#router->billing
foreach $ip (@bill_ip) {
 if ( grep $_ eq $ip, @ipfw_ip ) {
 } else {
 `/sbin/ipfw table 11 delete $ip`;
 print "$ip unblocked\n";
 }
}

I hate 'grep' in the loops, and looking for better solution. Any advice?

UPD: difference function from Set::Functional helps me.

for(difference (\@ipfw_ip, \@bill_ip)) {
 ..._;
}
sub difference(@) {
 my $first = shift;
 return unless $first && @$first;
 my %set;
 undef @set{@$first};
 do { delete @set{@$_} if @$_ } for @_;
 return keys %set;
}
asked Jun 4, 2013 at 5:21
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

You can use Set::Functional to make the code very short:

use Set::Functional 'difference';
for(difference [@ipfw_ip], [@bill_ip]) {
 `/sbin/ipfw table 11 add $ip`;
 print "$ip blocked\n";
}

Another advantage of the approach above is that you don't have to worry about duplicate entries in the two arrays.

answered Jun 6, 2013 at 17:58
\$\endgroup\$
1
  • \$\begingroup\$ Thank you alot! I dislike new dependencies but looks into Set::Functional and see the code. Its simple. I will update my question with solution. \$\endgroup\$ Commented Jun 7, 2013 at 3:22
1
\$\begingroup\$

The completely procedural way to write the same is:

foreach my $fw_ip (@ipfw_ip) {
 foreach my $bill_ip (@bill_ip) {
 if($fw_ip eq $bill_ip) {
 ...
 last;
 }
 }
}

The main advantage is that it is easy to understand for anybody, and not using too much perl-fu.

I find it odd that you write

 if ( grep $_ eq $ip, @bill_ip ) {
 } else {
 `/sbin/ipfw table 11 add $ip`;
 print "$ip blocked\n";
 }

In stead of

 if ( not grep $_ eq $ip, @bill_ip ) {
 `/sbin/ipfw table 11 add $ip`;
 print "$ip blocked\n";
 }

or even

 unless ( grep $_ eq $ip, @bill_ip ) {
 `/sbin/ipfw table 11 add $ip`;
 print "$ip blocked\n";
 }

P.s. always use strict; and use warnings;. It looks as if you aren't.

answered Jun 4, 2013 at 19:09
\$\endgroup\$
2
  • \$\begingroup\$ 2xforeach the same then grep in foreach. I hope it possible do that task without loop in loop. And thank you about "if else" no idea how I writed that. Probably there was deleted code. \$\endgroup\$ Commented Jun 5, 2013 at 4:12
  • \$\begingroup\$ Sure - you can do the same completely without a loop. Will be back with that. \$\endgroup\$ Commented Jun 5, 2013 at 6:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.