SS891
SS891

Reputation: 39

Expand multiple for loop embedded inside Perl code

my $limit = 10;
my $new_limit = 20;

$command = '

some_plain_lines_here

foreach my $i (o..$limit-1) { print"
   some loop_lines_here with $i
";}

some_more_plain_lines_here

foreach my $j (0..$new_lmit-1) {print"
   some_more_loop_lines_here with $j
";}

some_more_nonloop_lines_here;
';

#TODO: How to scoop out individual for-loops from command and expand and put replace the result back.
my $out_line = eval $command;

I have a piece of code like above where I have a $command variable containing a mixture of text and foreach loops. The text comes from an XLS and this apparently weird format is to help users write content fast and automate rest in backend.

Now, if there's a single for loop, we can easily call eval and expand the content into an $out_line. However in this case we have to scoop out every foreach and then replace the expanded output in same location.

I am not sure how to split the content into an array at the foreach boundaries. If we get the array, we can call eval as required and expand/stitch back text.

It's essentially a string-to-array conversion problem, but gave the complete picture for clarity.

Upvotes: 1

Views: 106

Answers (1)

TLP
TLP

Reputation: 67900

Like I said in the comments, eval() is very dangerous and almost always unnecessary. You should basically never use it, except in very controlled and select situations, and certainly never when you do not control what is being eval'ed.

With something like this, you could do the same thing without eval. Assuming that the user input is the limits. Note that I am cleaning user input to make sure it is ok to use. You may even insert error feedback to the user, but do not reveal how the de-taint works.

use strict;
use warnings;   # always use these

my $limit     = shift;
my $new_limit = shift;       # user input

$limit     //= 10;           # default
$new_limit //= 20;

$limit     =~ s/[^0-9]+//g;  # de-taint input
$new_limit =~ s/[^0-9]+//g;

sub command {
    my ($limit, $new_limit) = @_;
    # some_plain_lines_here <--- dont know what this is supposed to be

    for my $i (0 .. $limit-1) { 
        print "some loop_lines_here with $i";
    }

    # some_more_plain_lines_here

    for my $j (0 .. $new_lmit-1) {
        print "some_more_loop_lines_here with $j";
    }

    # some_more_nonloop_lines_here;
}

#TODO: How to scoop out individual for-loops from command and expand and put replace the result back.
# ^-- no idea what this means

command($limit, $new_limit);     # execute the command

It is impossible to say what you could put in a subroutine like this without knowing more about what you are looking for. But you sure do not need eval() to perform a for loop and print.

Upvotes: 1

Related Questions