James
James

Reputation: 720

PHP preg_match error

I have been ripping my hair out trying to find out where this error is coming from. Any help resolving this error would be greatly appreciated.

ERROR:

Warning: preg_match() [function.preg-match]: Compilation failed: range out of order in character class at offset 9 in /home/internet/public_html/z-insert/functions/dns.php on line 526

CODE: -line 526 is the 4th preg_match

if (preg_match('/127\.[0-9]+\.[0-9]+\.[0-9]+/',$mx_ip[$i]) || 
preg_match('/10\.[0-9]+\.[0-9]+\.[0-9]+/',$mx_ip[$i]) ||
preg_match('/192\.168\.[0-9]+\.[0-9]+/',$mx_ip[$i]) ||
preg_match('/172\.[16-31]+\.[0-9]+\.[0-9]+/',$mx_ip[$i])){

Upvotes: 2

Views: 1167

Answers (3)

Nemoden
Nemoden

Reputation: 9056

First, as I commented, 16-31 is not a valid range. I suggest you to read this article about numeric ranges in regexps.

As a solution I propose:

* Capture second octet and check it with php:

$flag = false;
if (preg_match('/172\.(?P<second_octet>\d+)\.\d+\.\d+/',$mx_ip[$i], $match)) {
    if ($match['second_octet']>=16 && $match['second_cotet'] <= 31) {
        $flag = true;
    }
}
if (preg_match('/127\.[0-9]+\.[0-9]+\.[0-9]+/',$mx_ip[$i]) || 
preg_match('/10\.[0-9]+\.[0-9]+\.[0-9]+/',$mx_ip[$i]) ||
preg_match('/192\.168\.[0-9]+\.[0-9]+/',$mx_ip[$i]) || 
$flag
) { ...

* Pass numbers from 16 to 31 explicitly:

$second_octet_range = range(16,31);
preg_match('/172\.(?:'.implode('|', $second_octet_range).')\.\d+\.\d+/',$mx_ip[$i]);

* Go with less readable variant of your regular expression (IMHO, less preferable solution because of lack of readability - you really need some time to understand that second octet's range is 16-31 while in first 2 solutions it's obvious):

preg_match('/172\.(?:1[6-9]|2[0-9]|3[01])\.\d+\.\d+/',$mx_ip[$i]);

Upvotes: 2

codaddict
codaddict

Reputation: 455000

The character class [16-31] is not valid.

It tell: match any charter that is:

  1. either a 1 or any
  2. any in the range starting from 6 till 3 !!! Which is invalid range.
  3. either a 1

Looks like you want to match any number in the range 16 till 31 for that you can do:

1[6-9]|2[0-9]|3[01]

where you split the entire range of 16-31 into sub-ranges, write a regex for each sub-range and club all the sub-ranges using the | (or operator).

Upvotes: 2

Explosion Pills
Explosion Pills

Reputation: 191739

[] encloses a character class, which has no order. You can create ranges within the character class for convenience, but it must be of the correct syntax. You can't have the range 6-3. You need to do something like this:

(?:1[6-9]|2[0-9]|30|31)

I'm also not sure whether the + there is intentional, but I would guess not.

Upvotes: 3

Related Questions