字符类中的范围乱序

Ari*_*iod 22 php regex

我在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);
Run Code Online (Sandbox Code Playgroud)

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

<!--GSM PER NUMBER - 5550101 - START-->
Run Code Online (Sandbox Code Playgroud)

和:

<!--GSM PER NUMBER - 5550101 - END-->
Run Code Online (Sandbox Code Playgroud)

您是否有关于可能导致此错误的提示?

小智 71

嗨我得到了同样的错误并解决了它:

  Warning: preg_match(): Compilation failed: range out of order in character class at offset <N>
Run Code Online (Sandbox Code Playgroud)

研究阶段:

..范围乱序..所以定义了一个不能使用的范围.

..在偏移N ..我快速查看了我的正则表达式模式.位置N是" - ".它用于定义"az"或"0-9"等范围.

我只是逃过了" - ".

 \-    
Run Code Online (Sandbox Code Playgroud)

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

  • 好的,为什么这不被指定为正确的答案? (4认同)

小智 9

此错误是由于范围不正确引起的.例如:9-0 aZ要更正此问题,您必须将9-0更改为0-9并将aZ更改为a-zA-Z在您的情况下,您不会转义字符" - ",然后,preg_match尝试解析正则表达式并且失败并且范围不正确.逃避" - ",它必须解决你的问题.


tho*_*ter 8

如果$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);
Run Code Online (Sandbox Code Playgroud)

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


N R*_*ler 5

我收到此错误,顺序如下:

[/-.]
Run Code Online (Sandbox Code Playgroud)

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

[./-]
Run Code Online (Sandbox Code Playgroud)

  • 这是因为未转义的连字符。如果像第二个示例一样将连字符放在字符类的最后,则不需要对其进行转义。你也可以用以下方法解决这个问题:`[/\-.]`,即在连字符之前放置一个反斜杠。 (2认同)

rdi*_*diz 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);
Run Code Online (Sandbox Code Playgroud)