note 108927 added to regexp.reference.recursive
| From: | DanielKlein | Date: | Wed, 06 Jun 2012 04:18:43 +0000 |
| Subject: | note 108927 added to regexp.reference.recursive | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-188414@lists.php.net to get a copy of this message | ||
The order of non-mutually exclusive alternatives within a recursed sub-pattern is important.
<?php
$pattern = '/^(?<octet>[01]?\d?\d|2[0-4]\d|25[0-5])(?:\.(?P>octet)){3}$/';
?>
You might expect that this pattern will match any IP address in dotted-decimal notation (e.g.
'123.45.67.89'). The pattern is intended to match four octets in the following ranges:
0-9, 00-99 & 000-255, each separated by a single dot. However, only the first octet can include
values from 200-255; the remainder can only have values less than 200. The reason for this is that
if the rest of the pattern fails, recursion is not back-tracked into to find an alternative match.
The first part of the sub-pattern will match the first two digits of any octet from 200-255. The
rest of the pattern will then fail because the third digit in the octet does not match either
'\.' or '$'.
<?php
var_export(preg_match($pattern, '255.123.45.67')); // 1 (true)
var_export(preg_match($pattern, '255.200.45.67')); // 0 (false)
var_export(preg_match($pattern, '255.123.45.200')); // 0 (false)
?>
The correct pattern is:
<?php
$pattern = '/^(?<octet>25[0-5]|2[0-4]\d|[01]?\d?\d)(?:\.(?P>octet)){3}$/';
?>
Note that the first two alternatives are mutually exclusive so their order is unimportant. The third
alternative, however, is not mutually exclusive but it will now only match when the first two fail.
<?php
var_export(preg_match($pattern, '255.123.45.67')); // 1 (true)
var_export(preg_match($pattern, '255.200.45.67')); // 1 (true)
var_export(preg_match($pattern, '255.123.45.200')); // 1 (true)
?>
----
Server IP: 113.20.13.217
Probable Submitter: 202.59.29.222
----
Manual Page -- http://www.php.net/manual/en/regexp.reference.recursive.php
Edit -- https://master.php.net/note/edit/108927
Del: integrated -- https://master.php.net/note/delete/108927/integrated
Del: useless -- https://master.php.net/note/delete/108927/useless
Del: bad code -- https://master.php.net/note/delete/108927/bad+code
Del: spam -- https://master.php.net/note/delete/108927/spam
Del: non-english -- https://master.php.net/note/delete/108927/non-english
Del: in docs -- https://master.php.net/note/delete/108927/in+docs
Del: other reasons-- https://master.php.net/note/delete/108927
Reject -- https://master.php.net/note/reject/108927
Search -- https://master.php.net/manage/user-notes.php