bingohighway has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks,
I'd like to read and execute Perl code that is contained in an external file, but I'm not sure how to approach this.E.g.
#main Perl file my $var = 100; my $filename = "temp.txt"; open my IN, '<', $filename or die "Can't read '$filename': $!"; while (defined (my $line = <IN>)) { if($line =~ /^#/){ #execute perl if statement here #Do something based on if statement processed }; }; ## File to be read, temp.txt## Some random text, not Perl. #if($var == 100) output this text to a file #endif
So the code above is split into two sections. The main code, and the code to be read (temp.txt). The if statement in temp.txt is signified by a "#" and the 'if' command can be recognised by a regex. The bit within the brackets ($var == 100) I would like to just dump straight into a real if statement, (or even just execute 'if($var == 100)'). The reason for dumping is to avaid having to code all those operators and brackets!
So if that has confused you, in summary I'd basically like to selectively read Perl code from an external file and execute it!
Cheers!

Replies are listed 'Best First'.
Re: Reading and executing Perl
by targetsmart (Curate) on Apr 02, 2009 at 12:15 UTC

    You can use eval, but basically that is not a good method, if your that external file is changeable by every other users. Then you have very big problem on hand(`rm -rf /` is also possible there, how you would check it?).
    I think your requirement can be solved easily by adopting some other methods, not the one which you are talking about.

    Vivek
    -- In accordance with the prarabdha of each, the One whose function it is to ordain makes each to act. What will not happen will never happen, whatever effort one may put forth. And what will happen will not fail to happen, however much one may seek to prevent it. This is certain. The part of wisdom therefore is to stay quiet.
      Unfortunately it has to be done this way. It is basically translating a preprocessor style tagging system for a lot of old code that can't be altered.
      I'll give your suggestions a try, cheers!
        I see your point about 'rm' though. Currently I'm only allowing know tags through, hence the idea of stripping the 'if' and then using the code's own 'if'. Meaning only the logic section would be used. If that makes sense.
Re: Reading and executing Perl
by jethro (Monsignor) on Apr 02, 2009 at 12:26 UTC

    No need to worry, the solution is already here, lots of people already did this and put the code into CPAN. You might check out some templating modules like Template::Toolkit, Text::Template, Text::ScriptTemplate,Template::Simple, or just go to http://search.cpan.org/search?query=template&mode=all to get a huge list of Templating modules. Ok, some are geared towards HTML, but often they are general solutions.

    UPDATE: Your answers to targetsmart still leave questions open for me: Which parts are fixed and which can you design, change or add? Is the perl code fixed and already there or will it be added and by whom? Trusted or untrusted users?

Re: Reading and executing Perl
by ELISHEVA (Prior) on Apr 02, 2009 at 12:43 UTC
    In Perl you can compose statements for execution, including if clauses. Just calculate a string with the code you want to execute, and then call it with eval. The only tricky part is making sure that variables get evaluated only when you want them to be evaluated - when building the string or when executing the string. Here's an annotated example:
    use strict; use warnings; my $x=45; # \$x prevents $x from being evaluated when we build the # condition. my $sCondition="\$x == 100"; # we're resetting $x now just to prove that # $x will be evaluated later on when we eval the # generated code $x=100; # <<EOF is like "..." but for long multi-line strings # we didn't escape the $ in $sCondition # so $sCondition will be evaluated as part of $sPerl. # MAKE ABSOLUTELY SURE YOU TRUST THE VALUE OF $sCondition # before you use $sPerl. VERY BAD THINGS CAN HAPPEN IF # untrusted strings are used in generated code. # We don't need to declare $x (e.g. my $x) in the generated # code because eval uses variable declarations in the # surrounding code, e.g. the "my $x=45" above my $sPerl = <<EOF; if ($sCondition) { print "Hello, World\n"; } else { print "Goodbye, for now\n"; } 1; EOF # Note: $sPerl ends with 1; so that we are always # guaranteed to exit with a true value unless we # aborted due to an error (in which case eval will # return an undefined (i.e. false) value. # We will use that fact to detect problems in $sPerl # via the code pattern eval(...) or do {...} print "Evaluating:\n$sPerl"; eval($sPerl) or do { warn "Couldn't evaluate <$sPerl>" };

    Best, beth

Re: Reading and executing Perl
by Ish (Acolyte) on Apr 02, 2009 at 12:25 UTC
    You can also use "do 'filename.pl'". This does (excuse me) the same kind of thing as eval can and more. Similar security concerns apply though. Update<\b> See http://perldoc.perl.org/functions/do.html for more info
      'do filename' won't work here because the op doesn't have a complete perl file but random text interspersed with perl code. I don't see 'do' do any filtering.
        No, quite right. Should have read it a bit more carefully so that I didn't miss the bit that said 'random text, not Perl'.