in reply to Break the foreach loop on count on 50 and then insert a new foreach loop

Hello iamnewbie and welcome to the monastery and to wonderful world of Perl

Without enter in the merit of what are you trying to do, the basic question is: how can i interupt a loop every n iteration? use a counter. you can profit of the redo function and more generally speaking of the loop control. Search also ModernPerl for loop control (is here..).

Follow what this oneliner does:
perl -e "@list=(1..7);$counter=0; foreach $it (@list){if ($counter >= +3){print qq(\n\n);$counter = 0; redo}print qq($it\n); $counter++}" 1 2 3 4 5 6 7
Your case is more complicated because there is there also the port to be associated. But you'll do on your own.

That said i think is not the best strategy: a subroutine will be better and easier: the sub receive as input the port and address list, if that list is bigger than 50, it compose the command shifting the first 50 elements and recall itself with the same port and the remaining list, like (just a draft)
sub proces_no_more_than_50 { my($port,@addresses)=@_; if ($#addresses >= 50) { &execute( $port, map {shift @addresses} 1..50 ); } else{ &execute($port, @addresses); undef @addresses;} &proces_no_more_than_50($port,@addresses) if defined $addresses[0]; }


HtH
L*

There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

Replies are listed 'Best First'.
Re^2: Break the foreach loop on count on 50 and then insert a new foreach loop
by AnomalousMonk (Archbishop) on Nov 12, 2015 at 12:08 UTC

    Another possibility (also untested):

    use constant MAX => 50; sub process_up_to_MAX_at_a_time { my ($port, # comment @addresses, # ... ) = @_; while (@addresses > MAX) { my @sub_group = splice @addresses, 0, MAX; process_0_to_MAX($port, @sub_group); } process_0_to_MAX($port, @addresses); } sub process_0_to_MAX { ... }
    See splice. process_up_to_MAX_at_a_time() could also be made purely recursive... if you're into that sort of thing.

    BTW: Beware of comparisons like  $#addresses >= 50 when checking array size: it's an off-by-one pitfall. It seems ok in the  proces_no_more_than_50() example, but I find direct comparisons against an array (e.g.,  @addresses > 50) to be more intuitive and less error-prone in general. Also note that assignment to  $[ (but don't do that!) changes the value of  $#array (see perlvar). Evaluating  @array in scalar context always yields the number of elements in the array. (The  $[ special variable is deprecated as of Perl version 5.12; see the latest perlvar for its behavior after version 5.16. (Update: Better yet, check your local  perldoc perlvar for its behavior on your system — and then don't touch it.))


    Give a man a fish:  <%-{-{-{-<

      wise advices and good code AnomalousMonk! as usual

      iamnewbie be sure to understand the off-by-one pitfall explained by AnomalousMonk.

      L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      I had fixed my code with below resolution

      # Build up the match string portion of the iptables command: my @addresses2 = @$addresses; # Before Splice take backup in +to another variable while (scalar @addresses2) { my $matchString = "-m state"; $matchString .= " --state NEW"; $matchString .= " -m ${transport}"; $matchString .= " --protocol ${transport}"; $matchString .= " --dport ${portNum}"; $matchString .= " -s " . join(',', splice(@addresses2 +, 0, 50)); $matchString .= " -j ACCEPT"; # # Build the full command: my $cmd = "${appendCmd} --match=\"${matchString}\"";

      Hi @AnomalousMonk Between i couldn't really understand what you mean here with your code can you please explain.

        ... i couldn't really understand what you mean here with your code ...

        Is it the code for  process_up_to_MAX_at_a_time() or the discussion of the behavior of  $#array (or both) that you are asking about? In either case, can you please be more specific about the points you do not understand?


        Give a man a fish:  <%-{-{-{-<

Re^2: Break the foreach loop on count on 50 and then insert a new foreach loop
by iamnewbie (Novice) on Nov 13, 2015 at 05:55 UTC

    @Discipulus Please see what i did with the code and it works fine now but the problem is that it is executing one address at a time so it takes more time then it should take so is there a way i can make my new code more effiecient?

    See my new code below

    sub addRules { my %args = @_; my $protocol = $args{protocol}; my $ports = $args{ports}; my $addresses = $args{addresses}; my $domain = $args{domain}; my $appendCmd = "iptablesAdm append"; $appendCmd .= " --type=rule"; $appendCmd .= " --table=filter"; $appendCmd .= " --chain=INPUT"; $appendCmd .= " --protocol=${protocol}"; $appendCmd .= " --domain=${domain}"; $appendCmd .= " --persist=yes"; Dbug->debug("Base Insert CMD: ${appendCmd}"); # # Loop over the ports and create a rule for each of the addresses +with each port: foreach my $port (@$ports) { my $portNum = $port->port(); my $transport = $port->transportStr(); Dbug->log("Inserting rules for ${portNum} addresses @{$address +es}"); # # Build up the match string portion of the iptables command: foreach my $addr (@$addresses) { my $matchString = "-m state"; $matchString .= " --state NEW"; $matchString .= " -m ${transport}"; $matchString .= " --protocol ${transport}"; $matchString .= " --dport ${portNum}"; $matchString .= " -s $addr"; $matchString .= " -j ACCEPT"; # # Build the full command: my $cmd = "${appendCmd} --match=\"${matchString}\""; # # Run the command: Dbug->log("\tCMD: ${cmd}\n"); system($cmd) && do { Dbug->error("Rule insert failed!"); Dbug->error("CMD: ${cmd}"); return 0; }; } } # # As a side effect of getting the rules we will display what they +are right # now, and we would like to see what things look like after adding + this # rule: printRules('protocol' => $protocol, 'domain' => $domain); return 1; }