preg_match():编译失败:偏移处的字符类中的无效范围

时间:2014-07-15 17:11:20

标签: php regex preg-match

提前感谢您抽出时间帮助解决这个问题。

  

preg_match():编译失败:第278行偏移20 session.php的字符类无效范围

在我们的服务器上进行PHP升级后,经过数月的工作后,它突然停止工作。

这是代码

    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");
     }
  }

7 个答案:

答案 0 :(得分:20)

字符类范围是使用 - 在字符类中的两个值(正则表达式中为[])之间定义的。 [0-9]表示0到9之间的所有内容,包括0和9。在代码中的正则表达式中,您有多个字符类范围a-z0-9。还有一个类你可能并不想放在那里,即_-\s

"/^[a-z0-9]([0-9a-z_-\s])+$/i"
                   ^^^^ 

在某些(大多数?)版本的PCRE(PHP使用的正则表达式库)中,这显然不被视为无效字符范围,但最近可能已更改,如果PCRE库已在服务器上升级,则可能是原因。

Debuggex是一个很好的工具,可以帮助调试错误(好吧,PHP的错误消息告诉你行错误所在的字符,所以..)像这(我不是附属的,只是一个粉丝)。

答案 1 :(得分:4)

您的错误取决于您的正则表达式解释器。

您可以转义连字符以明确其用途。表示使用\-代替-

您的最终代码:

/^[a-z0-9]([0-9a-z_\-\s])+$/i

答案 2 :(得分:1)

也许这个答案可以拯救阿拉伯/波斯语Slug创作:

对于 php 版本是 7.3 使用 \- 而不是 -

<块引用>

[^a-z0-9_\s-

<块引用>

"/[\s-_]+/"

所以对于 php 7.3 的阿拉伯语 make_slug 函数:

function make_slug($string, $separator = '-')
{
    $string = trim($string);
    $string = mb_strtolower($string, 'UTF-8');

    // Make alphanumeric (removes all other characters)
    // this makes the string safe especially when used as a part of a URL
    // this keeps latin characters and Persian characters as well
    $string = preg_replace("/[^a-z0-9_\s\-ءاآؤئبپتثجچحخدذرزژسشصضطظعغفقكکگلمنوهی]/u", '', $string);

    // Remove multiple dashes or whitespaces or underscores
    $string = preg_replace("/[\s\-_]+/", ' ', $string);

    // Convert whitespaces and underscore to the given separator
    $string = preg_replace("/[\s_]/", $separator, $string);

    return $string;
}

答案 3 :(得分:0)

这个问题确实很老,但是有一些涉及PHP 7.3的新开发和较新的版本需要涵盖。 PHP PCRE引擎迁移到PCRE2 ,这就是Backward Incompatible Changes的来源:

  
      
  • 内部库API已更改
  •   
  • 'S'修饰符无效,系统会自动研究模式。没有实际影响。
  •   
  • “ X”修饰符是PCRE2中的默认行为。当前补丁将行为恢复为PCRE中的“ X”含义,但最好采用新行为并默认情况下启用“ X”。所以目前也没有影响。
  •   
  • 已发现由于更新的Unicode引擎而导致的某些行为更改。 PCRE2中为Unicode 10,而PCRE中为Unicode 7。某些行为改变可以通过无效的模式看到。
  •   

在PHP 7.3之前,如果逃脱了连字符或将其放在"in a position where it cannot be interpreted as indicating a range"中,则可以在字符类的任何位置使用连字符。现在,为了将连字符放入字符类中,总是只在开始或结束位置使用它

另请参阅此参考文献:

  

简单来说,

  PCRE2在模式验证方面更加严格,因此升级后,您现有的某些模式将无法再编译。   

  这是php.net中使用的简单代码段   

preg_match('/[\w-.]+/', ''); // this will not work in PHP7.3
preg_match('/[\w\-.]+/', ''); // the hyphen need to be escaped
     

从上面的示例中可以看到,两行之间有一点点但实质性的区别。

答案 4 :(得分:0)

我遇到此错误,我通过执行此操作来解决

Route::get('{path}','HomeController@index')->where( 'path', '([A-z]+)?' );

这对我有用。

答案 5 :(得分:0)

我在Larave路线中遇到了同样的错误,我这样解决。

Route::get('/{any}', 'SpaController@index')->where('any', '.*');

答案 6 :(得分:-2)

首先, 路线:: get('{path}',“ HomeController @ index”)-> where('path','([[A-z \ d-/ _。] +)?');

当我从下面尝试并发生时,它对我不起作用:-)

Route :: get('{path}','HomeController @ index')-> where('path','([[A-z] +)?')