简体   繁体   English

如何验证正则表达式?

[英]How can I validate regex?

I'd like to test the validity of a regular expression in PHP, preferably before it's used.我想测试 PHP 中正则表达式的有效性,最好是在使用它之前。 Is the only way to do this actually trying a preg_match() and seeing if it returns FALSE ?执行此操作的唯一方法是实际尝试preg_match()并查看它是否返回FALSE吗?

Is there a simpler/proper way to test for a valid regular expression?是否有更简单/正确的方法来测试有效的正则表达式?

// 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);

As the user pozs said, also consider putting @ in front of preg_match() ( @preg_match() ) in a testing environment to prevent warnings or notices.正如用户pozs所说,还可以考虑在测试环境中将@放在 preg_match()@preg_match() )前面,以防止出现警告或通知。

To validate a RegExp just run it against null (no need to know the data you want to test against upfront) .要验证 RegExp,只需针对null运行它(无需预先知道要测试的数据) If it returns explicit false ( === false ), it's broken.如果它返回显式 false ( === false ),则它已损坏。 Otherwise it's valid though it need not match anything.否则它是有效的,尽管它不需要匹配任何东西。

So there's no need to write your own RegExp validator.所以没有必要编写自己的 RegExp 验证器。 It's wasted time...真是浪费时间...

I created a simple function that can be called to checking preg我创建了一个简单的函数,可以调用它来检查 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()];
}

You can call this function using the follow code :您可以使用以下代码调用此函数:

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

Alternative - Regular Expression Online Tester替代方案 - 正则表达式在线测试器

If you want to dynamically test a regex preg_match(...) === false seems to be your only option.如果您想动态测试正则表达式preg_match(...) === false似乎是您唯一的选择。 PHP doesn't have a mechanism for compiling regular expressions before they are used. PHP 没有在使用正则表达式之前对其进行编译的机制。

Also you may find preg_last_error an useful function.此外,您可能会发现preg_last_error是一个有用的功能。

On the other hand if you have a regex and just want to know if it's valid before using it there are a bunch of tools available out there.另一方面,如果您有一个正则表达式并且只想在使用它之前知道它是否有效,那么那里有很多可用的工具。 I found rubular.com to be pleasant to use.我发现rubular.com使用起来很愉快。

You can check to see if it is a syntactically correct regex with this nightmare of a regex, if your engine supports recursion (PHP should).如果您的引擎支持递归(PHP 应该),您可以使用正则表达式的噩梦来检查它是否是语法正确的正则表达式。

You cannot, however algorithmically tell if it will give the results you want without running it.但是,您无法通过算法判断它是否会在不运行它的情况下给出您想要的结果。

From: Is there a regular expression to detect a valid regular expression?来自: 是否有正则表达式来检测有效的正则表达式?

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

Without actually executing the regex you have no way to be sure if it's be valid.如果不实际执行正则表达式,您将无法确定它是否有效。 I've recently implemented a similar RegexValidator for Zend Framework.我最近为 Zend 框架实现了一个类似的 RegexValidator。 Works just fine.工作得很好。

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

You can validate your regular expression with a regular expression and up to a certain limit .您可以使用正则表达式验证您的正则表达式达到一定的限制 Checkout this stack overflow answer for more info.查看此堆栈溢出答案以获取更多信息。

Note: a "recursive regular expression" is not a regular expression, and this extended version of regex doesn't match extended regexes.注意:“递归正则表达式”不是正则表达式,这个扩展版本的正则表达式不匹配扩展的正则表达式。

A better option is to use preg_match and match against NULL as @Claudrian said正如@Claudrian 所说,一个更好的选择是使用preg_match并匹配 NULL

I am not sure if it supports PCRE, but there is a Chrome extension over at https://chrome.google.com/webstore/detail/cmmblmkfaijaadfjapjddbeaoffeccib called RegExp Tester .我不确定它是否支持 PCRE,但在https://chrome.google.com/webstore/detail/cmmblmkfaijaadfjapjddbeaoffeccib上有一个名为RegExp Tester的 Chrome 扩展。 I have not used it as yet myself so I cannot vouch for it, but perhaps it could be of use?我自己还没有使用它,所以我不能保证它,但也许它可能有用?

I'd be inclined to set up a number of unit tests for your regex.我倾向于为您的正则表达式设置一些单元测试。 This way not only would you be able to ensure that the regex is indeed valid but also effective at matching.这样,您不仅可以确保正则表达式确实有效,而且在匹配方面也有效。

I find using TDD is an effective way to develop regex and means that extending it in the future is simplified as you already have all of your test cases available.我发现使用 TDD 是开发 regex 的一种有效方法,这意味着将来扩展它会被简化,因为您已经拥有所有可用的测试用例。

The answer to this question has a great answer on setting up your unit tests. 这个问题的答案对设置单元测试有很好的回答。

So in summary, for all those coming to this question you can validate regular expressions in PHP with a function like this.所以总而言之,对于所有提出这个问题的人,您可以使用这样的函数验证 PHP 中的正则表达式。

preg_match() returns 1 if the pattern matches given subject, 0 if it does not, or FALSE if an error occurred.如果模式匹配给定的主题,preg_match() 返回 1,如果不匹配,则返回 0,如果发生错误,则返回 FALSE。 - PHP Manual - 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()];
}

Which can be used like this.哪个可以这样使用。

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

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

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

just use the easy way - look if the preg_match is return a false value:只需使用简单的方法 - 查看 preg_match 是否返回错误值:

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

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

You should try to match the regular expression against NULL .您应该尝试将正则表达式与NULL匹配。 If the result is FALSE ( === FALSE ), there was an error.如果结果为 FALSE ( === FALSE ),则存在错误。

In PHP >= 5.5, you can use the following to automatically get the built-in error message, without needing to define your own function to get it:在 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()];
}

Try it online! 在线尝试!

Note that the call to preg_match() will still throw a warning for invalid regular expressions.请注意,对preg_match()的调用仍会针对无效的正则表达式发出警告。 The warning can be caught with a custom error handler using set_error_handler() .可以使用set_error_handler()使用自定义错误处理程序捕获警告。

See Can I try/catch a warning?请参阅我可以尝试/捕获警告吗? . .

According to the PCRE reference , there is no such way to test validity of an expression, before it's used.根据PCRE 参考,在使用表达式之前,没有这种方法可以测试表达式的有效性。 But i think, if someone use an invalid expression, it's a design error in that application, not a run-time one, so you should be fine.但我认为,如果有人使用无效的表达式,这是该应用程序中的设计错误,而不是运行时错误,所以你应该没问题。

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

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