关于php:我如何验证正则表达式?

How can I validate regex?

我想在PHP中测试正则表达式的有效性,最好是在使用它之前。唯一的方法是尝试一个preg_match(),看看它是否返回FALSE

是否有更简单/正确的方法来测试有效的正则表达式?


1
2
3
4
// This is valid, both opening ( and closing )
var_dump(preg_match('~Valid(Regular)Expression~', null) === false);
// This is invalid, no opening ( for the closing )
var_dump(preg_match('~InvalidRegular)Expression~', null) === false);

正如用户pozs所说,还可以考虑将@放在测试环境中的preg_Match()(@preg_match()前面,以防止出现警告或通知。

要验证一个regexp,只需在null上运行它(不需要知道要在前端测试的数据)。如果它返回显式错误(=== false),则它将被破坏。否则它是有效的,尽管它不需要匹配任何东西。

所以不需要编写自己的regexp验证器。浪费时间…


我创建了一个简单的函数,可以调用它来检查preg

1
2
3
4
5
6
7
8
9
10
11
12
13
function is_preg_error()
{
    $errors = array(
        PREG_NO_ERROR               => 'Code 0 : No errors',
        PREG_INTERNAL_ERROR         => 'Code 1 : There was an internal PCRE error',
        PREG_BACKTRACK_LIMIT_ERROR  => 'Code 2 : Backtrack limit was exhausted',
        PREG_RECURSION_LIMIT_ERROR  => 'Code 3 : Recursion limit was exhausted',
        PREG_BAD_UTF8_ERROR         => 'Code 4 : The offset didn\'t correspond to the begin of a valid UTF-8 code point',
        PREG_BAD_UTF8_OFFSET_ERROR  => 'Code 5 : Malformed UTF-8 data',
    );

    return $errors[preg_last_error()];
}

可以使用以下代码调用此函数:

1
2
preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
echo is_preg_error();

替代-正则表达式在线测试仪

  • 雷格西尔
  • PHP正则表达式测试仪
  • 正则表达式工具


如果您想动态测试一个regex preg_match(...) === false,似乎是您唯一的选择。PHP没有在使用正则表达式之前编译它们的机制。

另外,您可能会发现preg_last_错误是一个有用的函数。

另一方面,如果您有一个regex,只是想知道它在使用之前是否有效,那么有很多可用的工具。我觉得rubular.com很好用。


如果您的引擎支持递归(php应该),那么您可以通过这个regex的噩梦检查它是否是语法正确的regex。

但是,从算法上讲,如果不运行它,就无法判断它是否会给出您想要的结果。

发件人:是否有用于检测有效正则表达式的正则表达式?

1
/^((?:(?:[^?+*{}()[\]\\|]+|\\.|\[(?:\^?\\.|\^[^\\]|[^\\^])(?:[^\]\\]+|\\.)*\]|\((?:\?[:=!]|\?<[=!]|\?>)?(?1)??\)|\(\?(?:R|[+-]?\d+)\))(?:(?:[?+*]|\{\d+(?:,\d*)?\})[?+]?)?|\|)*)$/


如果不执行regex,就无法确定它是否有效。我最近为Zend框架实现了类似的regexvalidator。工作很好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
class Nuke_Validate_RegEx extends Zend_Validate_Abstract
{
    /**
     * Error constant
     */

    const ERROR_INVALID_REGEX = 'invalidRegex';

    /**
     * Error messages
     * @var array
     */

    protected $_messageTemplates = array(
        self::ERROR_INVALID_REGEX =>"This is a regular expression PHP cannot parse.");

    /**
     * Runs the actual validation
     * @param string $pattern The regular expression we are testing
     * @return bool
     */

    public function isValid($pattern)
    {
        if (@preg_match($pattern,"Lorem ipsum") === false) {
            $this->_error(self::ERROR_INVALID_REGEX);
            return false;
        }
        return true;
    }
}

我不确定它是否支持PCRE,但是在https://chrome.google.com/webstore/detail/cmmblmkfaijaadfjapjdbeaoffeccib有一个chrome扩展名为regexp tester。我还没有自己用过它,所以我不能担保它,但也许它是有用的?


总之,对于所有涉及到这个问题的人,您可以用这样的函数验证PHP中的正则表达式。

preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred. - PHP Manual

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * Return an error message if the regular expression is invalid
 *
 * @param string $regex string to validate
 * @return string
 */

function invalidRegex($regex)
{
    if(preg_match($regex, null) !== false)
    {
        return '';
    }

    $errors = array(
        PREG_NO_ERROR               => 'Code 0 : No errors',
        PREG_INTERNAL_ERROR         => 'Code 1 : There was an internal PCRE error',
        PREG_BACKTRACK_LIMIT_ERROR  => 'Code 2 : Backtrack limit was exhausted',
        PREG_RECURSION_LIMIT_ERROR  => 'Code 3 : Recursion limit was exhausted',
        PREG_BAD_UTF8_ERROR         => 'Code 4 : The offset didn\'t correspond to the begin of a valid UTF-8 code point',
        PREG_BAD_UTF8_OFFSET_ERROR  => 'Code 5 : Malformed UTF-8 data',
    );

    return $errors[preg_last_error()];
}

可以这样使用。

1
2
3
4
if($error = invalidRegex('/foo//'))
{
    die($error);
}

您可以使用正则表达式来验证正则表达式,并达到一定的限制。有关详细信息,请签出此堆栈溢出应答。

注意:"递归正则表达式"不是正则表达式,而且此扩展版本的regex与扩展的regex不匹配。

一个更好的选择是使用preg_match并与空匹配,正如@claudrian所说。


您应该尝试将正则表达式与null匹配。如果结果是错误的(=== false),则出现错误。

在php>=5.5中,您可以使用以下命令自动获取内置错误消息,而无需定义自己的函数即可获取:

1
2
preg_match($regex, NULL);
echo array_flip(get_defined_constants(true)['pcre'])[preg_last_error()];

我倾向于为您的regex设置一些单元测试。这样不仅可以确保regex确实有效,而且在匹配时也有效。

我发现使用TDD是开发regex的有效方法,这意味着在将来扩展regex会简化,因为您已经拥有了所有可用的测试用例。

这个问题的答案对于设置单元测试有很好的答案。


根据PCRE参考,在使用表达式之前,没有这样的方法来测试它的有效性。但我认为,如果有人使用了一个无效的表达式,那是该应用程序中的设计错误,而不是运行时错误,所以您应该很好。