EricR
EricR

Reputation: 1497

Perl eval command not working as expected

I have a sort of perl "terminal" (pastebin code) we'll call it that I've written, the idea behind writing it is I wanted to run perl code line by line, allowing me to run new commands on existing (large) data sets, without having to change a script and reload the data set and re-run my script.

(Mind you, I wrote this almost a year ago now, and it was mostly a learning experiment (with a dynamic function tablet), however now I have some use for it and discovered some issues which are preventing me from utilising it.)

As such, I eval user entered commands, however, they aren't behaving as expected and perhaps someone can shed some light on why this would be.

This is the 'important' bit, I have the command line data stored in @args, and the first element of that is stored in $prog. I check if there's an existing function (I allow users to create functions, and really abuse references to get an action table) if not I try and eval the command.

if(exists($actions{$prog})){
        print "\n";
        $actions{$prog}->(@args);
        print "\n";
}else{
        print "\nEVALing '$command'\n";
        eval $command;
        warn $@ if $@;
        print "\n";
}

As can be seen below, it works as expected for the assignment of scalars, but fails with the assignment of arrays and hashes.

user@host:~/$ perl term.pl 
1358811935>$a = 0;
EVALing '$a = 0;'

1358811937>print $a;
EVALing 'print $a;'
0
1358811944>@b = qw(2 3);                                                                                                      
EVALing '@b = qw(2 3);'
Global symbol "@b" requires explicit package name at (eval 5) line 1.

1358811945>print @b;
EVALing 'print @b;'
Global symbol "@b" requires explicit package name at (eval 6) line 1.

1358812008>my @b = qw(2 3);                                                                                                   
EVALing 'my @b = qw(2 3);'

1358812008>print "@b";
EVALing 'print "@b";'
Possible unintended interpolation of @b in string at (eval 9) line 1.
Global symbol "@b" requires explicit package name at (eval 9) line 1.

1358812016>print join(',',@b);                                                                                                
EVALing 'print join(',',@b);'
Global symbol "@b" requires explicit package name at (eval 10) line 1.

1358812018>

Upvotes: 1

Views: 1226

Answers (2)

ysth
ysth

Reputation: 98378

For this kind of thing, you probably want to allow arbitrary package variables to be used by saying no strict 'vars';. Declaring a lexical (my) variable in the eval'd code will work, but will no longer be in scope for the next eval.

Alternatively, pre-declare a set of variables for the eval'd code to use (perhaps including a %misc hash).

A completely different approach is to each time through eval a concatenation of all the code entered so far (if printing output is a factor, redirecting output up until the most recent code entered).

Upvotes: 1

choroba
choroba

Reputation: 241738

Variables $a and $b are special, because they are used by sort. Therefore, strict does not complain if they are not declared. Using $x would trigger the same error as arrays and hashes.

Upvotes: 3

Related Questions