繁体   English   中英

如何验证正则表达式?

[英]How can I validate regex?

我想测试 PHP 中正则表达式的有效性,最好是在使用它之前。 执行此操作的唯一方法是实际尝试preg_match()并查看它是否返回FALSE吗?

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

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

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

要验证 RegExp,只需针对null运行它(无需预先知道要测试的数据) 如果它返回显式 false ( === false ),则它已损坏。 否则它是有效的,尽管它不需要匹配任何东西。

所以没有必要编写自己的 RegExp 验证器。 真是浪费时间...

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

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()];
}

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

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

替代方案 - 正则表达式在线测试器

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

此外,您可能会发现preg_last_error是一个有用的功能。

另一方面,如果您有一个正则表达式并且只想在使用它之前知道它是否有效,那么那里有很多可用的工具。 我发现rubular.com使用起来很愉快。

如果您的引擎支持递归(PHP 应该),您可以使用正则表达式的噩梦来检查它是否是语法正确的正则表达式。

但是,您无法通过算法判断它是否会在不运行它的情况下给出您想要的结果。

来自: 是否有正则表达式来检测有效的正则表达式?

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

如果不实际执行正则表达式,您将无法确定它是否有效。 我最近为 Zend 框架实现了一个类似的 RegexValidator。 工作得很好。

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

您可以使用正则表达式验证您的正则表达式达到一定的限制 查看此堆栈溢出答案以获取更多信息。

注意:“递归正则表达式”不是正则表达式,这个扩展版本的正则表达式不匹配扩展的正则表达式。

正如@Claudrian 所说,一个更好的选择是使用preg_match并匹配 NULL

我不确定它是否支持 PCRE,但在https://chrome.google.com/webstore/detail/cmmblmkfaijaadfjapjddbeaoffeccib上有一个名为RegExp Tester的 Chrome 扩展。 我自己还没有使用它,所以我不能保证它,但也许它可能有用?

我倾向于为您的正则表达式设置一些单元测试。 这样,您不仅可以确保正则表达式确实有效,而且在匹配方面也有效。

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

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

所以总而言之,对于所有提出这个问题的人,您可以使用这样的函数验证 PHP 中的正则表达式。

如果模式匹配给定的主题,preg_match() 返回 1,如果不匹配,则返回 0,如果发生错误,则返回 FALSE。 - PHP 手册

/**
 * 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()];
}

哪个可以这样使用。

if($error = invalidRegex('/foo//'))
{
    die($error);
}

您可以使用 T-Regx 中的valid()

pattern('InvalidRegular)Expression')->valid(); // bool (false)

只需使用简单的方法 - 查看 preg_match 是否返回错误值:

//look is a regex or not
$look = "your_regex_string";

if (preg_match("/".$look."/", "test_string") !== false) {
    //regex_valid
} else {
    //regex_invalid
}

您应该尝试将正则表达式与NULL匹配。 如果结果为 FALSE ( === FALSE ),则存在错误。

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

// For PHP >= 8, use the built-in strEndsWith instead of this function.
// Taken from https://www.php.net/manual/en/function.str-ends-with.php#125967
function endsWith($haystack, $needle) {
    $length = strlen($needle);
    return $length > 0 ? substr($haystack, -$length) === $needle : true;
}

function test_regex($regex) {
    preg_match($regex, NULL);
    $constants = get_defined_constants(true)['pcre'];
    foreach ($constants as $key => $value) {
        if (!endsWith($key, '_ERROR')) {
            unset($constants[$key]);
        }
    }
    return array_flip($constants)[preg_last_error()];
}

在线尝试!

请注意,对preg_match()的调用仍会针对无效的正则表达式发出警告。 可以使用set_error_handler()使用自定义错误处理程序捕获警告。

请参阅我可以尝试/捕获警告吗? .

根据PCRE 参考,在使用表达式之前,没有这种方法可以测试表达式的有效性。 但我认为,如果有人使用无效的表达式,这是该应用程序中的设计错误,而不是运行时错误,所以你应该没问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM