Passing Regexes

To pass regexes around, you'll need to be using a release of Perl sufficiently recent as to support the qr// construct, pass around strings and use an exception-trapping eval, or else be very, very clever.

Here's an example of how to pass in a string to be regex compared using qr//:

    sub compare($$) {
        my ($val1, $regex) = @_;
        my $retval = $val1 =~ /$regex/;
	return $retval;
    }
    $match = compare("old McDonald", qr/d.*D/i);
Notice how qr// allows flags at the end. That pattern was compiled at compile time, although it was executed later. The nifty qr// notation wasn't introduced until the 5.005 release. Before that, you had to approach this problem much less intuitively. For example, here it is again if you don't have qr//:

    sub compare($$) {
        my ($val1, $regex) = @_;
        my $retval = eval { $val1 =~ /$regex/ };
	die if $@;
	return $retval;
    }
    $match = compare("old McDonald", q/($?i)d.*D/);
Make sure you never say something like this:

    return eval "\$val =~ /$regex/";   # WRONG
or someone can sneak shell escapes into the regex due to the double interpolation of the eval and the double-quoted string. For example:

    $pattern_of_evil = 'danger ${ system("rm -rf * &") } danger';
    eval "\$string =~ /$pattern_of_evil/";
Those preferring to be very, very clever might see the O'Reilly book, Mastering Regular Expressions, by Jeffrey Friedl. Page 273's Build_MatchMany_Function() is particularly interesting. A complete citation of this book is given in perlfaq2.


Back to perlfaq7