7

Firstly, I was wondering if there was some kind of built in function that would check to see if a regex pattern was valid or not. I don't want to check to see if the expression works - I simply want to check it to make sure that the syntax of the pattern is valid - if that's possible.

If there is no built in function to do so, how do I do it on my own? Do I even need to?

Is there a directory of built in functions/modules that I can search so I can avoid more questions like this? Thank you.

EDIT: I should mention that I plan on generating these patterns on the fly based on user input - which is why I'd like to validate them to make sure they will actually run.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339

4 Answers4

23

I am no Perl expert, but maybe this can help:

#!/usr/bin/perl

my $pattern = "["; # <-insert your pattern here
my $regex = eval { qr/$pattern/ };
die "invalid regex: $@" if $@;

which returns this:

invalid regex: Unmatched [ in regex; marked by <-- HERE in m/[ <-- HERE / at test.pl line 4.

For your second question you could always check out the huge body of work at CPAN.

mechanical_meat
  • 163,903
  • 24
  • 228
  • 223
  • 2
    If this is for a server, consider very carefully how you will avoid letting the user generated input execute arbitrary code. I don't know, offhand, how it could happen but that's no assurance. – George Phillips Jul 11 '09 at 07:58
  • @George: This is a very good point, thank you for mentioning. – mechanical_meat Jul 11 '09 at 07:59
  • 1
    I was at borders today, and the perl cookbook suggested eval as well. –  Jul 14 '09 at 06:37
1

I'm not quite sure what you mean by "valid" here. If the expression is syntactically out of whack (say, missing a bracket), then the interpreter will let you know and your program won't compile.

But that doesn't protect you from logical or semantic errors. That is, your regular expression may be valid Perl but do terrible things—or do nothing at all. Maybe you want something like YAPE::Regex::Explain which will produce an explanation of your regular expression.

Telemachus
  • 19,459
  • 7
  • 57
  • 79
1

Another cpan module that you can use: Regexp::Parser. From the documentation:

my $parser = Regexp::Parser->new;
if (! $parser->regex($rx)) {
  my $errmsg = $parser->errmsg;
  my $errnum = $parser->errnum;
  # ...
}
user2291758
  • 715
  • 8
  • 19
0

For example, in a Bash script:

#!/bin/bash

pattern='12[3';
printf '%s' "$pattern" | perl -ne 'eval { qr/$_/ }; die if $@;';
echo $?;

# Outputs (if the pattern is invalid):
#
# Unmatched [ in regex; marked by <-- HERE in m/12[ <-- HERE 3/ at -e line 1, # <> line 1.
#         ...propagated at -e line 1, <> line 1.
# 255

# If valid:
#
# 0

or

#!/bin/bash

pattern='12[3';

if
    printf '%s' "$pattern" \
    | perl -ne 'eval { qr/$_/ }; die if $@;' &> '/dev/null';
then
    printf 'Valid\n';
else
    printf 'Invalid\n';
fi

Also, it should be possible to use environment variables:

#!/bin/bash

export pattern='12[3';

if perl -ne 'eval { qr/$ENV{pattern}/ }; die if $@;' &> '/dev/null';
then #...

Related: Reference 1, Reference 2

Artfaith
  • 1,183
  • 4
  • 19
  • 29