Testing for a Valid Pattern

Problem

You want to let users enter their own patterns, but an invalid one would abort your program the first time you tried to use it.

Solution

Test the pattern in an eval {} construct first, matching against some dummy string. If $@ is not set, no exception occurred, so you know the pattern successfully compiled as a valid regular expression. Here is a loop that continues prompting until the user supplies a valid pattern:

do {
    print "Pattern? ";
    chomp($pat = <>);
    eval { "" =~ /$pat/ };
    warn "INVALID PATTERN $@" if $@;
} while $@;

Here’s a standalone subroutine that verifies whether a pattern is valid.

sub is_valid_pattern {
    my $pat = shift;
    return eval { "" =~ /$pat/; 1 } || 0;
}

That one relies upon the block returning 1 if it completes, which in the case of an exception, never happens.

Discussion

There’s no end to patterns that won’t compile. The user could mistakenly enter "<I\s*[^>", "*** GET RICH ***", or "+5-i". If you blindly use the proffered pattern in your program, it will cause an exception, normally a fatal event.

The tiny program in Example 6.9 demonstrates this.

Example 6-9. paragrep

#!/usr/bin/perl
# paragrep - trivial paragraph grepper
die "usage: $0 pat [files]\n" unless @ARGV;
$/ = '';
$pat = shift;
eval { "" =~ /$pat/; 1 }      or die "$0: Bad pattern $pat: $@\n";
while (<>) {
    print "$ARGV $.: $_" if /$pat/o;
}

That /o is a promise to Perl that the interpolated variable’s contents are constant over the program’s entire run. It’s an efficiency ...

Get Perl Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.