如何捕获无效的 preg_match 模式?

9

我正在编写一个PHP脚本,该脚本接受用户输入的正则表达式模式,并将其用于preg_match()函数。如何检查该模式是否有效?

7个回答

9
根据文档,preg_match()在发生错误时会返回FALSE。问题是它也会抛出一个警告。解决这个问题的一种方法是抑制错误消息的输出,捕获返回值,并在其为false时使用error_get_last()输出错误。类似于以下内容:
$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

在生产环境中,您可能不需要错误报告位 - 这取决于您的设置。


2
你知道的,使用 @ 并不是被禁止的 :p - Artefacto
如果 $match === false - webbiedave
@Artefacto 是的,但它看起来太丑了!:) @webbiedave 谢谢,已经纠正了。 - Pekka
这个代码适用于任何情况吗?我试着用 preg_match_all()(肯定返回 false)来测试,但它只是返回 null(我知道当没有错误时它会这样做)。 - Adam Lynch
@Adam 我猜应该没问题。你确定你输入的是有问题的正则表达式吗?很奇怪。 - Pekka
@Pekka,问题出在pcre.backtrack_limit上。我原以为不是回溯限制的问题,因为那一行被注释掉了,而取消注释并没有任何影响……但事实证明,将它加三个零就可以了;http://stackoverflow.com/questions/9121654/why-would-this-regex-return-an-error。这让我想知道,如果达到了限制,preg_match_all()为什么不会返回false呢? - Adam Lynch

5

仅仅是测试一下。 如果模式无效,preg_match()将返回FALSE

返回值:preg_match()返回 模式匹配的次数。 这将是0次(没有匹配)或1次, 因为preg_match()在第一次匹配后停止搜索。 相反地,preg_match_all()会一直继续, 直到达到主题的末尾。如果发生错误,则preg_match()返回FALSE。


2

2

一个简单的解决方案是使用“@”来抑制警告,然后在之后检查错误:

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

您正在搜索的字符串(在本例中为$ip)和preg_match的返回值 - 如果您只想检查正则表达式的语法,则并不重要。

0

我以为在MRE中看到过这个方法;结果发现是Friedl自己写的。这是清单


0

自从这个问题被提出(并得到回答)以来,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){
        return str_replace("preg_match(): ", "", error_get_last()["message"]);
        //Make it prettier by removing the function name prefix
    }
    return NULL;
}

演示


-1
if (preg_match($regex, $variable)) {
    echo 'Valid';
}
else {
    echo 'InValid';
}

2
你必须使用 preg_match(...)!==false 进行检查,因为它可以返回 0,即使它是有效的但不匹配。 - mck89
你应该与FALSE进行比较:if (preg_match($regex, $variable) !== FALSE) {。该模式可以是有效的,但没有匹配项。请参阅文档 - Lekensteyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接