php preg_match(): 编译失败: 字符类偏移范围无效
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24764212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
preg_match(): Compilation failed: invalid range in character class at offset
提问by user3841888
Thank you in advance for you time in helping with this issue..
提前感谢您抽出时间帮助解决这个问题。
preg_match(): Compilation failed: invalid range in character class at offset 20 session.php on line 278
preg_match():编译失败:第 278 行偏移 20 session.php 处的字符类中的范围无效
This stopped working all of a sudden after months of working, after a PHP upgrade on our server.
在我们的服务器上升级 PHP 后,经过几个月的工作,这突然停止工作。
Here is the code
这是代码
else{
/* Spruce up username, check length */
$subuser = stripslashes($subuser);
if(strlen($subuser) < $config['min_user_chars']){
$form->setError($field, "* Username below ".$config['min_user_chars']."characters");
}
else if(strlen($subuser) > $config['max_user_chars']){
$form->setError($field, "* Username above ".$config['max_user_chars']."characters");
}
/* Check if username is not alphanumeric */
/* PREG_MATCH CODE */
else if(!preg_match("/^[a-z0-9]([0-9a-z_-\s])+$/i", $subuser)){
$form->setError($field, "* Username not alphanumeric");
}
/* PREG_MATCH CODE */
/* Check if username is reserved */
else if(strcasecmp($subuser, GUEST_NAME) == 0){
$form->setError($field, "* Username reserved word");
}
/* Check if username is already in use */
else if($database->usernameTaken($subuser)){
$form->setError($field, "* Username already in use");
}
/* Check if username is banned */
else if($database->usernameBanned($subuser)){
$form->setError($field, "* Username banned");
}
}
回答by Wiktor Stribi?ew
The problem is really old, but there are some new developments related to PHP 7.3 and newer versions that need to be covered. PHP PCRE engine migrates to PCRE2, and the PCRElibrary version used in PHP 7.3 is 10.32, and that is where Backward Incompatible Changesoriginate from:
这个问题真的很老,但是有一些与 PHP 7.3 和更新版本相关的新开发需要覆盖。PHP PCRE 引擎迁移到 PCRE2,PHP 7.3 中使用的 PCRElibrary 版本是 10.32,这就是Backward Incompatible Changes 的起源:
- Internal library API has changed
- The 'S' modifier has no effect, patterns are studied automatically. No real impact.
- The 'X' modifier is the default behavior in PCRE2. The current patch reverts the behavior to the meaning of 'X' how it was in PCRE, but it might be better to go with the new behavior and have 'X' turned on by default. So currently no impact, too.
- Some behavior change due to the newer Unicode engine was sighted. It's Unicode 10 in PCRE2 vs Unicode 7 in PCRE. Some behavior change can be sighted with invalid patterns.
- 内部库 API 已更改
- 'S' 修饰符无效,自动研究模式。没有实际影响。
- “X”修饰符是 PCRE2 中的默认行为。当前补丁将行为恢复为 PCRE 中“X”的含义,但最好采用新行为并默认打开“X”。所以目前也没有影响。
- 由于较新的 Unicode 引擎,一些行为发生了变化。它是 PCRE2 中的 Unicode 10 与 PCRE 中的 Unicode 7。使用无效模式可以看到一些行为变化。
Acc. to the PHP 10.33 changelog:
累积 到 PHP 10.33 更新日志:
- With
PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
set, escape sequences such as\s
which are valid in character classes, but not as the end of ranges, were being treated as literals. An example is[_-\s]
(but not[\s-_]
because that gave an error at the startof a range). Now an "invalid range" error is given independently ofPCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
.
- 使用
PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
set 时,诸如\s
在字符类中有效但不作为范围结束的转义序列被视为文字。一个例子是[_-\s]
(但不是[\s-_]
因为在范围开始时出现错误)。现在,“无效范围”错误独立于PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
.
Before PHP 7.3, you might use the hyphen in a character class in any position if you escaped it, or if you put it "in a position where it cannot be interpreted as indicating a range". In PHP 7.3, it seems the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
was set to false. So, from now on, in order to put hyphen into a character class, always use it either at the start or end positions only.
在 PHP 7.3 之前,您可以在字符类中的任何位置使用连字符,如果您对其进行转义,或者如果您将其放在“不能被解释为指示范围的位置”。在 PHP 7.3 中,似乎PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
设置为 false。因此,从现在开始,为了将连字符放入字符类,请始终仅在开始或结束位置使用它。
See also this reference:
另请参阅此参考:
In simple words,
PCRE2 is more strict in the pattern validations, so after the upgrade, some of your existing patterns could not compile anymore.
Here is the simple snippet used in php.netpreg_match('/[\w-.]+/', ''); // this will not work in PHP7.3 preg_match('/[\w\-.]+/', ''); // the hyphen need to be escapedAs you can see from the example above there is a little but substantial difference between the two lines.
简单来说,
PCRE2在模式验证上更加严格,所以升级后,你现有的一些模式不能再编译了。
这是 php.net 中使用的简单片段preg_match('/[\w-.]+/', ''); // this will not work in PHP7.3 preg_match('/[\w\-.]+/', ''); // the hyphen need to be escaped正如您从上面的示例中看到的,两条线之间存在微小但实质性的差异。
回答by MatsLindh
A character class range is defined by using - between two values in a character class ([]
in regex). [0-9]
means everything between 0 and 9, inclusive. In the regular expression in your code, you have several character class ranges, a-z
, 0-9
. There is also one class that you probably didn't mean to put there, namely _-\s
.
字符类范围是通过在字符类中的两个值之间使用 - 来定义的([]
在正则表达式中)。[0-9]
表示 0 到 9 之间的所有内容,包括 0 和 9。在代码中的正则表达式中,您有几个字符类范围,a-z
, 0-9
。还有一个你可能不想放在那里的类,即_-\s
.
"/^[a-z0-9]([0-9a-z_-\s])+$/i"
^^^^
This is apprently not considered an invalid character range in some (most?) versions of PCRE (the regular expression library PHP uses), but it might have changed recently, and if the PCRE library was upgraded on the server, that might be the reason.
在某些(大多数?)版本的 PCRE(PHP 使用的正则表达式库)中,这显然不被认为是无效的字符范围,但它最近可能发生了变化,如果 PCRE 库在服务器上升级,这可能是原因.
Debuggexis a nice tool that can help debug errors (well, the error message from PHP told you both the line andthe character where the error was, so..) like this (I'm not affiliated, just a fan).
Debuggex是一个很好的工具,可以帮助调试错误(好吧,来自 PHP 的错误消息告诉你错误所在的行和字符,所以..)像这样(我没有附属,只是一个粉丝)。
回答by Moradnejad
Your error is dependent on your regex interpreter.
您的错误取决于您的正则表达式解释器。
You can escape hyphen to be clear about its use. Meaning using \-
instead of -
.
您可以转义连字符以明确其用途。意思是使用\-
代替-
。
Your final code:
您的最终代码:
/^[a-z0-9]([0-9a-z_\-\s])+$/i
回答by Vince
i have this error and i solve it by doing this
我有这个错误,我通过这样做来解决它
Route::get('{path}','HomeController@index')->where( 'path', '([A-z]+)?' );
Route::get('{path}','HomeController@index')->where( 'path', '([A-z]+)?' );
and it is work for me.
这对我来说很有效。