≡ Menu

6 Perl Eval Function Examples – Regex, Error Handling, Require, Timeout, Dynamic Code

Perl eval built-in function is very powerful. In this article let us review how to use regex in eval, trapping errors using eval, create dynamic code using eval, insert a code from a file/sub-routine using eval etc.,

The general form of perl eval expects a expression or a block of code as an argument.

1. Differences Between Various Perl Eval Statements

Let us consider the following perl code snippet:

$expr = ‘$a + $b’;
eval $expr; # 1
eval “$expr”; # 2
eval ‘$expr’; # 3
eval { $expr }; # 4

Case #1 and #2 are identical where perl identifies them as a valid executable statement and evaluates the expression. So, it would produce the result as “30”.

In case #3, the expression cannot be expanded. So, it gives actual expression ($a + $b) as a result. This wont be commonly used by anyone.

Case #4 is identical to case #3, but the statements inside the block is validated for syntax errors at compile time.

2. Regular Expressions Handling with Eval

With the use of eval, we can reduce the number of lines in the code considerably when it needs to match the line for more than a number of regular expressions.

The list of regular expressions can be put into a container (hash / array), and in a loop the regular expressions can be taken one by one and matches with the input line as shown below.

$line = <>;
%hash = (
number     => qr/^[0-9]+$/,
alphabets   => qr/^[a-zA-Z]+$/
);

while( my ($key,$value) = each(%hash) ) {
if(eval    "$line =~ /$value/") {
print "$key\n";
}
}

3. Perl Eval Error Handling – Trapping Errors

Eval is used to trap the errors. During the execution of the subroutine the program might die because of errors, or external calling of die function. During this time, if the block of perl code is executed inside the eval, then program continues to run even after the die or errors, and it also captures the errors or dieing words.

Zero Divide Error:

eval  { $average =  $total / $count };
print “Error captured : $@\n”;

In the above, $count contains the value as 0. When we run the code without the eval block, the program gets exit.

Run After Die

sub func
{
die “dieing in subroutine func\n”;
}
eval { func(); };
print “Error captured : $@\n”;

Perl eval can’t catch following errors:

  • Uncaught signal
  • Running out of memory
  • Syntax errors

4. Dynamic Perl Code Using Eval

Eval can compile and executes code from a string at runtime. So, we can write the dynamic perl program using eval.

print “Enter number 1 : ”;
$data1 = ;
print “Enter number 2 : ”;
$data2 = ;
print “Enter operator : ”;
$operator = ;
$str = “$data1 $operator $data2”;
$result = eval “$data1 $operator $data2”;

We can execute any number of statements in eval. The result of the eval is the last evaluated expression.

We should be care in using eval on a string, as it might execute untrusted data from a string. If the assignment operations has to be done in the string itself, we should be care on handling the lvalue.

$str = “\$result = $data1 $operator $data2”;
eval { $str };

5. Inserting Perl Script From a File or Subroutine during Run Time

In perl we can dynamically load modules at run time. To load modules dynamically, we have to use “require” ( not “use”).
Sample code to load module when the input file is a compressed one,

$filetype = `file $InputFile`;

if($filetype =~ /gzip compressed/) {
print  "compressed input file...\n";
eval { require PerlIO::gzip; };
}

Common subroutines that are used in the programs can be separated into a file that can be loaded into the perl programs by eval as shown below.

File :  common_routines.pl
sub open_file
{
....
}
sub read_file
{
....
}
sub write_file
{
....
}
sub close_file
{
....
}
In the perl script,
sub load_file_subroutines
{
open CODE, 'common_routines.pl';
undef $\;
my $code = <code>;
close CODE;
eval $code;
die $@ if $@;
}</code>

6. Perl Eval in Input Time-Outs

The alarm standard library function is used to generate SIGALRM signal after a certain time. This would mainly helps us to avoid the blocking wait on the user input. This can be used with eval to get the user input within a specified time as shown in the example below.

$SIG{ALRM} = \&input_timed_out;
eval {
alarm (10);
$buf = <>;
alarm(0);           # Cancel the pending alarm if user responds.
};
if ($@ =~ /NO USER INPUT IN TIME/) {
print "Timed out.\n";
}
sub input_timed_out {
die "NO USER INPUT IN TIME";
}
Add your comment

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

Comments on this entry are closed.

  • Fredo May 26, 2010, 11:06 am

    I strongly advise against the use of string-eval that you describe in section 2. You invoke the parser and the compiler every time you use it and you don’t get compile-time warnings on the code.

    It is much more reliable to use the qr// Operator:

    # enable newer perl features (say)
    use 5.010;

    my %hash = (
    number => qr/^[0-9]+$/,
    alphabets => qr/^[a-zA-Z]+$/,
    );

    # I intend to use the diamond-operator in the next line – hopefully the comment function doesn’t destroy it
    while (<>) {
    while ( my($key, $value) = each %hash ) {
    say $key if /$value/;
    }
    }

  • Meir Guttman August 27, 2010, 3:47 am

    Dear Mr. Mariyappan

    Excellent article! The first one that actually helped me to use the construct in its many facets. Thanks!

    I apologize though for my nit picking, but here goes…

    In your very first discussion, you give an example and then you say:

    ‘Case #1 and #2 are identical where Perl identifies them as a valid executable statement and evaluates the expression. So, it would produce the result as “30”.’

    You never show numerical values for either $a or $b so the presumed result of ’30’ is a bit out of place, right?

    Many many regards,
    Meir

  • Tay Joc Cing February 22, 2011, 9:11 pm

    Thanks for the timeout example!

  • Sean July 6, 2011, 4:32 pm

    Thanks, great to have some good examples of eval().

  • mug896 November 20, 2014, 8:13 pm

    In section 5
    undef $\; needs to replace with undef $/;