preg_match编译失败:字符类中的范围无效

时间:2014-12-11 15:38:29

标签: php regex validation laravel

我使用Laravel作为我的框架,并且我尝试使用自己的preg_match函数来验证表单。

以下是我的代码:

Validator::extend('alpha_num_spaces', function ($attribute, $value)
{
    return preg_match('/^([-a-z0-9_-\s])+$/i', $value);
});

现在,我已经在生产服务器上运行它,但它在我收到的本地计算机上运行正常:

preg_match(): Compilation failed: invalid range in character class at offset 13

我的猜测与PHP版本的差异有关?但我完全基于这个猜测。或者也许正则表达式存在一些错误?

提前致谢。

3 个答案:

答案 0 :(得分:5)

“我的猜测与PHP版本的差异有关”。实际上,我认为生产服务器的版本将\s视为文字s并忽略反斜杠。 (当然,测试带有空格的字符串)。但是你的测试服务器会看到一个字符和一个速记字符类之间的范围,这显然没有任何意义。

最近版本的PCRE足够聪明(当它是明确的时候),当一个连字符前面有一个速记字符类或一个范围时,它不会定义一个字符范围。例如:[\s-ABC][0-9-ABC]是正确的。(在这些情况下,您无需转义)

结论,你可以写:

[-a-z0-9_\s]
[a-z0-9_\s-]
[a-z0-9-_\s]
[a-z-0-9_\s]
[a-z0-9\s-_]
[a-z0-9_\-\s]

但不是:

[a-z0-9_-\s]

答案 1 :(得分:4)

您需要使用:

preg_match('/^([-a-z0-9_\s])+$/i', $value);

OR

preg_match('/^([-\w\s])+$/i', $value);

你的角色类中间有一个未转义的连字符。

连字符需要在角色类的第一个或最后一个位置或者它应该被转义。此外,你已经在第一个地方有一个连字符,所以不需要再次使用连字符。

答案 2 :(得分:2)

连字符必须是最后一个字符,如果您希望它是匹配的字符之一:

return preg_match('/^([-a-z0-9_\s-])+$/i', $value);