9

I am writing a PHP script that accepts a regular expression pattern from the user which is used by preg_match(). How can I check that the pattern is valid?

Liam
  • 19,819
  • 24
  • 83
  • 123

7 Answers7

9

According to the docs,

preg_match() returns FALSE if an error occurred.

the problem is that it will also throw a warning.

One way to deal with this is is to suppress the output of the error message, catch the return value, and output the error using error_get_last() if it was false.

Something like

$old_error = error_reporting(0); // Turn off error reporting

$match = preg_match(......);

if ($match === false) 
 {
   $error = error_get_last();
   echo $error["message"];
 }

error_reporting($old_error);  // Set error reporting to old level

You may not need the error reporting bit in a production environment - it depends on your setup.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 2
    You know, it's not forbidden to use `@` :p – Artefacto Sep 14 '10 at 16:06
  • Should be `if ($match === false)` – webbiedave Sep 14 '10 at 17:55
  • @Artefacto true, but it looks so *ugly*! :) @webbiedave cheers, corrected. – Pekka Sep 14 '10 at 18:09
  • Should this work for anything? Trying it with `preg_match_all()` (which is definitely returning `false`) and it's just returning `null` (which I know it does when there wasn't an error). – Adam Lynch Feb 03 '12 at 22:20
  • @Adam I guess it should. You're sure you're feeding it a faulty regex? Strange. – Pekka Feb 03 '12 at 22:35
  • @Pekka It was the `pcre.backtrack_limit`. I thought it wasn't the backtrack limit because that line was commented out and uncommenting it made no difference... but it turns out that adding three zeroes to it did; http://stackoverflow.com/questions/9121654/why-would-this-regex-return-an-error. Which makes me wonder why wouldn't an error be registered if the limit was hit and preg_match_all() returned false – Adam Lynch Feb 03 '12 at 22:44
5

Just test it. preg_match() will return FALSE if the pattern is not valid.

Return values: preg_match() returns the number of times pattern matches. That will be either 0 times (no match) or 1 time because preg_match() will stop searching after the first match. preg_match_all() on the contrary will continue until it reaches the end of subject. preg_match() returns FALSE if an error occurred.

Amal Murali
  • 75,622
  • 18
  • 128
  • 150
Lekensteyn
  • 64,486
  • 22
  • 159
  • 192
2

You can use preg_last_error() to get responses. Detail page:

http://php.net/manual/en/function.preg-last-error.php

Thanks!

Vijay
  • 491
  • 5
  • 3
2

One simple solution is to suppress the warning with an "@" and then check the error afterwards:

@preg_match($match, $ip);
if ( preg_last_error() != PREG_NO_ERROR ) {
   echo("<p>Syntax error in regular expression ".htmlentities($match)."</p>\n");
}

The string you are searching for ($ip in this case) and the preg_match return value - does not matter if all you want to do is check the syntax of the regular expression.

drchuck
  • 4,415
  • 3
  • 27
  • 30
0

I thought I had seen a method for this in MRE; turns out it was one Friedl wrote himself. Here's the listing.

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
0

PHP has progressed quite a bit since this question was first asked (and answered). Since PHP 5.2 you can simply write the following to, not only test if the regular expression is valid, but to get the detailed error message if it's not:

if(@preg_match($pattern, '') === false){
   echo error_get_last()["message"];
}

Placed in a function

/**
 * Return an error message if the given pattern argument or its underlying regular expression
 * are not syntactically valid. Otherwise (if they are valid), NULL is returned.
 *
 * @param $pattern
 *
 * @return string|null
 */
function regexHasErrors($pattern): ?string
{
    if(@preg_match($pattern, '') === false){
        return str_replace("preg_match(): ", "", error_get_last()["message"]);
        //Make it prettier by removing the function name prefix
    }
    return NULL;
}

Demo

dearsina
  • 4,774
  • 2
  • 28
  • 34
-1
if (preg_match($regex, $variable)) {
    echo 'Valid';
}
else {
    echo 'InValid';
}
Alex Pliutau
  • 21,392
  • 27
  • 113
  • 143
  • 2
    You must use preg_match(...)!==false to check it because it can return 0 if it's valid but does not match – mck89 Sep 14 '10 at 15:44
  • You should be comparing to FALSE: `if (preg_match($regex, $variable) !== FALSE) {`. The pattern can be valid, with no matches. See [docs](http://nl2.php.net/manual/en/function.preg-match.php) – Lekensteyn Sep 14 '10 at 15:44