【问题标题】:Range out of order in character class字符类中的范围乱序
【发布时间】:2011-03-28 05:25:31
【问题描述】:

我在 preg_match() 函数中遇到了这个奇怪的错误:

警告:preg_match():编译失败:偏移 54 处的字符类范围乱序

造成这种情况的行是:

preg_match("/<!--GSM\sPER\sNUMBER\s-\s$gsmNumber\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s$gsmNumber\s-\sEND-->/s", $fileData, $matches);

这个正则表达式的作用是解析一个 HTML 文件,只提取以下部分:

<!--GSM PER NUMBER - 5550101 - START-->

和:

<!--GSM PER NUMBER - 5550101 - END-->

您对可能导致此错误的原因有提示吗?

【问题讨论】:

  • 检查变量 $gsmNumber,这可能是原因。
  • 我推荐阅读这个stackoverflow.com/questions/3148240/… - 您可能已经尝试在字符类中定义数字范围。
  • 我是为 [a-Z] 得到的(注意大写)。当它说范围时,它的意思只是[a-z] 输入正则表达式。

标签: php regex


【解决方案1】:

您好,我遇到了同样的错误并解决了:

  Warning: preg_match(): Compilation failed: range out of order in character class at offset <N>

研究阶段:

.. Range out of order .. 所以定义了一个不能使用的范围。

.. at offset N .. 我快速查看了我的正则表达式模式。位置 N 是“-”。它用于定义“a-z”或“0-9”等范围。

解决方案

我只是逃避了“-”。

 \-    

现在它被解释为字符“-”而不是范围!

【讨论】:

    【解决方案2】:

    此错误是由不正确的范围引起的。例如:9-0 a-Z 要更正此问题,您必须将 9-0 更改为 0-9 并将 a-Z 更改为 a-zA-Z 在您的情况下,您没有转义字符“-”,然后 preg_match 尝试解析正则表达式并因范围不正确而失败。 避开“-”,它必须解决你的问题。

    【讨论】:

      【解决方案3】:

      如果$gsmNumber 包含方括号、反斜杠或各种其他特殊字符,则可能会触发此错误。如果可能,您可能需要验证它以确保它实际上是在此之前的数字。

      2016 年编辑:

      有一个PHP函数可以转义正则表达式中的特殊字符:preg_quote()

      像这样使用它:

      preg_match(
        '/<!--GSM\sPER\sNUMBER\s-\s' .
        preg_quote($gsmNumber, '/') . '\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s' .
        preg_quote($gsmNumber, '/') . '\s-\sEND-->/s', $fileData, $matches);
      

      显然在这种情况下,因为您已经使用了两次相同的字符串,所以您可以先将引用的版本分配给一个变量并重新使用它。

      【讨论】:

      • krang 的答案可能是对这个特定问题更相关的答案 - 假设 $gsmNumber 是一个数字,那么问题将在于未转义的连字符。
      【解决方案4】:

      我按以下顺序收到此错误:

      [/-.]
      

      只需将. 移到开头即可解决问题:

      [./-]
      

      【讨论】:

      • 这是因为未转义的连字符。如果像第二个示例一样将连字符放在字符类的最后,则不需要对其进行转义。您也可以通过以下方式解决此问题:[/\-.] 即在连字符前放置一个反斜杠。
      【解决方案5】:

      虽然其他答案是正确的,但令我惊讶的是,在正则表达式中使用变量之前,没有人建议使用 preg_quote() 转义变量。因此,如果您要匹配一个实际的括号或任何其他在正则表达式中表示某事的东西,那将被转换为文字标记:

      $escaped = preg_quote($gsmNumber);
      preg_match( '/<!--GSM\sPER\sNUMBER\s-\s'.$escaped.'\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s'.$escaped.'\s-\sEND-->/s', $fileData, $matches);
      

      【讨论】:

        【解决方案6】:

        您可能有人插入了包含 +、-、( 和/或 ) 字符的手机号码,并在 preg_match 中按原样使用这些号码,因此您可能希望在使用之前对提供的数据进行清理(即通过剥离这些字符完全出来)。

        【讨论】:

        • 除了剥离这些字符之外,您还可以转义它们,即将它们标记为文字字符,请参阅docs.php.net/preg_quote
        【解决方案7】:

        这是几个 PHP 版本中的错误,因为我刚刚验证了当前 5.3.5 版本,与 Windows XP 家庭版上的 XAMPP 1.7.4 打包在一起。

        即使是一些非常简单的例子也能说明问题,例如,

            $pattern = '/^[\w_-. ]+$/';
            $uid = 'guest';
            if (preg_match($pattern, $uid)) echo 
              ("<style> p { text-decoration:line-through } </style>");
        

        自 2010 年 1 月 10 日以来,PHP 人员就已经知道该错误。 见http://pear.php.net/bugs/bug.php?id=18182。 该错误被标记为“关闭”但仍然存在。

        【讨论】:

        • 这不是错误,您提供的正则表达式不正确。
        猜你喜欢
        • 2013-07-17
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多