测试正则表达式在PHP中是否有效


Test if a regular expression is a valid one in PHP

我正在编写一个表单验证类,希望在验证中包含正则表达式。因此,所提供的正则表达式不能保证是有效的。

如何(有效地)检查正则表达式是否有效?

preg_*调用中使用该模式。如果函数返回false,那么您的模式可能有问题。据我所知,这是检查正则表达式模式在PHP中是否有效的最简单方法。


下面是一个指定正确类型布尔检查的示例:

$invalidPattern = 'i am not valid regex';
$subject = 'This is some text I am searching in';
if (@preg_match($invalidPattern, $subject) === false) {
    // the regex failed and is likely invalid
}

当您有错误报告时,您不能简单地测试布尔结果。如果正则表达式失败,将引发警告(即"警告:找不到结束分隔符xxx"。)

我觉得奇怪的是,PHP文档告诉这些抛出的警告。

下面是我使用try,catch解决这个问题的方法。

//Enable all errors to be reported. E_WARNING is what we must catch, but I like to have all errors reported, always.
error_reporting(E_ALL);
ini_set('display_errors', 1);
//My error handler for handling exceptions.
set_error_handler(function($severity, $message, $file, $line)
{
    if(!(error_reporting() & $severity))
    {
        return;
    }
    throw new ErrorException($message, $severity, $severity, $file, $line);
});
//Very long function name for example purpose.
function checkRegexOkWithoutNoticesOrExceptions($test)
{
    try
    {
        preg_match($test, '');
        return true;
    }
    catch(Exception $e)
    {
        return false;
    }
}

您不应该使用@来消除所有错误,因为它还可以消除致命错误。

function isRegularExpression($string) {
  set_error_handler(function() {}, E_WARNING);
  $isRegularExpression = preg_match($string, "") !== FALSE;
  restore_error_handler();
  return isRegularExpression;
}

这只会使preg_match调用的警告静音。

任何仍在关注anno 2018这个问题并使用php7的人都应该使用try/catch。

try { 
    preg_match($mypattern, '');
} catch ('Throwable $exception) {
    // regex was invalid and more info is in $exception->getMessage()
}

PHP自从第一次提出(并回答)这个问题以来已经取得了长足的进步。现在,您可以(PHP 5.2+)简单地将以下内容写入,不仅可以测试正则表达式是否有效,还可以获得详细的错误消息(如果不是):

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

放置在功能中

/**
 * 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){
        //Silence the error by using a @
        return str_replace("preg_match(): ", "", error_get_last()["message"]);
        //Make it prettier by removing the function name prefix
    }
    return NULL;
}

演示

如果表达式出现问题,这是我使用即将到来的警告的解决方案

function isRegEx($test)
{
    $notThisLine = error_get_last();
    $notThisLine = isset($notThisLine['line']) ? $notThisLine['line'] + 0 : 0;
    while (($lines = rand(1, 100)) == $notThisLine);
    eval(
        str_repeat("'n", $lines) . 
        '@preg_match(''' . addslashes($test) . ''', '''');'
    );
    $check = error_get_last();
    $check = isset($check['line']) ? $check['line'] + 0 : 0;
    return $check == $notThisLine;
}