问题 测试PHP中的正则表达式是否为有效表达式


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

我怎样(有效地)检查正则表达式是否有效?


7133
2018-01-11 18:56


起源



答案:


使用你的模式 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
}

17
2018-01-11 19:01



只是为了强调,这是严格的(===)布尔值 false,而不是虚假(==)价值如 0。 - Wiseguy
@CrazeD根据调用的函数和传递的选项,它可能是各种值。对于上述如果 $subject 不匹配 $pattern,并且有效,它将返回 0。然而, preg_replace 将返回 NULL 失败而不是假。您只需要查看您正在使用的特定功能的文档。 - Charles Sprayberry
@cspray我建议先用你的preg_ *调用@来抑制PHP警告。即 if (@preg_match($possiblyInvalidPattern, '') === false)  根据您的不同,这可能是也可能不是问题 使用error_reporting 水平。 - Ben
切勿使用@运算符。自从 - twicejr
虽然我当然同意你不应该使用 @ 在几乎所有情况下,操作员都有边缘情况需要使用它。这肯定是其中一个边缘案例。 - Charles Sprayberry


答案:


使用你的模式 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
}

17
2018-01-11 19:01



只是为了强调,这是严格的(===)布尔值 false,而不是虚假(==)价值如 0。 - Wiseguy
@CrazeD根据调用的函数和传递的选项,它可能是各种值。对于上述如果 $subject 不匹配 $pattern,并且有效,它将返回 0。然而, preg_replace 将返回 NULL 失败而不是假。您只需要查看您正在使用的特定功能的文档。 - Charles Sprayberry
@cspray我建议先用你的preg_ *调用@来抑制PHP警告。即 if (@preg_match($possiblyInvalidPattern, '') === false)  根据您的不同,这可能是也可能不是问题 使用error_reporting 水平。 - Ben
切勿使用@运算符。自从 - twicejr
虽然我当然同意你不应该使用 @ 在几乎所有情况下,操作员都有边缘情况需要使用它。这肯定是其中一个边缘案例。 - Charles Sprayberry


您不应该使用@来消除所有错误,因为它也会使致命错误无声。

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

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


2
2017-11-06 10:57





当您有错误报告时,您无法简单地测试布尔结果。如果正则表达式失败则抛出警告(即'警告:未找到结束分隔符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;
    }
}

1
2018-05-07 20:34





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

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;
}

-7
2018-02-28 18:58



-1代码不清楚, rand(), eval() 和 + 0。 - Dan Lugg
说真的,我已经设法回到这里,我仍然完全不知道这个片段;到底是做什么的? - Dan Lugg
这是一个自定义编码的try-catch。阅读非常可怕但它可能有效。我只想使用try-catch。 - twicejr