如何验证正则表达式?

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

有没有更简单/更合适的方法来测试一个有效的正则表达式?

41761 次浏览

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

你也许会发现 错误是一个很有用的函数。

另一方面,如果你有一个正则表达式,只是想知道它是否有效,然后再使用它有一大堆工具可用。我发现 Rubular.com使用起来很舒服。

我创建了一个简单的函数,可以调用它来检查 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();

可选正则表达式在线测试器

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

正如用户 波兹所说,也 考虑将 @放在 preg _ match ()前面(@preg_match())在测试环境中防止出现警告或通知。

要验证 RegExp,只需对 null (不需要知道要预先测试的数据)运行它。如果它返回显式的 false (=== false) ,那么它就被破坏了。否则它是有效的,虽然它不需要匹配任何东西。

因此,没有必要编写自己的 RegExp 验证器。

如果不实际执行正则表达式,就无法确定它是否有效。我最近为 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;
}
}

您可以使用 正则表达式达到一定的限度来验证正则表达式。

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

更好的选择是使用 preg_match并将 NULL 作为@Claudrian 进行匹配

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

我发现使用 TDD 是开发正则表达式的一种有效方式,并且由于您已经拥有了所有可用的测试用例,因此在将来扩展它可以得到简化。

这个问题的答案在设置单元测试方面有很好的答案。

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

所以总的来说,对于那些来到这个问题的人来说,您可以使用这样的函数来验证 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);
}

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

无论如何,在不运行它的情况下,算法都不能告诉您它是否会给出您想要的结果。

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

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

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

应该尝试将正则表达式与 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()的自定义错误处理程序可以捕获该警告。

参见 我能试着听听警告吗?

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

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