简体   繁体   中英

Range out of order in character class

I'm getting this odd error in the preg_match() function:

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

The line which is causing this is:

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

What this regular expression does is parse an HTML file, extracting only the part between:

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

and:

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

Do you have a hint about what could be causing this error?

Hi I got the same error and solved it:

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

Research Phase:

.. Range out of order .. So there is a range defined which can't be used.

.. at offset N .. I had a quick look at my regex pattern. Position N was the "-". It's used to define ranges like "az" or "0-9" etc.

Solution

I simply escaped the "-".

 \-    

Now it is interpreted as the character "-" and not as range!

This error is caused for an incorrect range. For example: 9-0 aZ To correct this, you must change 9-0 to 0-9 and aZ to a-zA-Z In your case you are not escaping the character "-", and then, preg_match try to parse the regex and fail with an incorrect range. Escape the "-" and it must solve your problem.

If $gsmNumber contains a square bracket, backslash or various other special characters it might trigger this error. If that's possible, you might want to validate that to make sure it actually is a number before this point.

Edit 2016:

There exists a PHP function that can escape special characters inside regular expressions: preg_quote() .

Use it like this:

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

Obviously in this case because you've used the same string twice you could assign the quoted version to a variable first and re-use that.

I was receiving this error with the following sequence:

[/-.]

Simply moving the . to the beginning fixed the problem:

[./-]

While the other answers are correct, I'm surprised to see that no-one has suggested escaping the variable with preg_quote() before using it in a regex. So if you're looking to match an actual bracket or anything else that means something in regex, that'll be converted to a literal token:

$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);

您可能让人们插入手机号码,包括 +、-、( 和/或 ) 字符,并在 preg_match 中按原样使用它们,因此您可能希望在使用之前清理提供的数据(即通过完全去除这些字符) .

This is a bug in several versions of PHP, as I have just verified for the current 5.3.5 version, as packaged with XAMPP 1.7.4 on Windows XP home edition.

Even some very simple examples exhibit the problem, eg,

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

The PHP folks have known about the bug since 1/10/2010. See http://pear.php.net/bugs/bug.php?id=18182 . The bug is marked "closed" yet persists.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM