|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2017-01-16 14:24 UTC] tomasyorke at hotmail dot com
Description:
------------
Using preg_match_all with the PREG_SET_ORDER flag and an optional capture group might return either an empty string or a missing element.
This depends on whether there is a matched capture group after the non-matched capture group.
From an interface perspective, this means that I have to check for two representations to test whether an optional capture group was matched.
The test script demonstrates such a case.
When considering a fix, the first priority should be that whatever the representation is (NULL, an empty string or a missing element.), it should be consistent, no matter if there is a matched capture group after or not.
If this cannot be fixed due to backwards compatibility Issues. Could we add a PREG_KEEP_NONMATCHES or PREG_SET_ORDER_2 flag?
Test script:
---------------
<?php
preg_match_all("#(a)?(b)(c)?#","b",$matches,PREG_SET_ORDER);
var_dump($matches);
Expected result:
----------------
array(1) {
[0] => array(3) {
[0] => string(1) "b" [1] => string(0) "" [2] => string(1) "b" [3] => string(0) ""
}
}
Actual result:
--------------
array(1) {
[0] => array(3) {
[0] => string(1) "b" [1] => string(0) "" [2] => string(1) "b"
}
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 15:00:01 2025 UTC |
Actually I can. Yay for Linux on Windows! ~/php/master/bin# ./php <?php var_dump(preg_match('/(a)?(b)?(c)?/', 'b', $matches), $matches); int(1) array(3) { [0]=> string(1) "b" [1]=> NULL [2]=> string(1) "b" } [1] is clearly NULL but there is no [3] for the unmatched (c)? group.As noted by cmb, this bug does not appear with the PREG_PATTERN_ORDER flag. Thus I switched the flag and my code to use PREG_PATTERN_ORDER and implemented my own preg_set_order() function. But I found a nearly identical bug with the PREG_OFFSET_CAPTURE flag. Consider the code preg_match_all("#(a)?(b)(c)?#","b",$matches,PREG_OFFSET_CAPTURE); var_dump($matches); Returns array(4) { [0] => array(1) { [0] => array(2) { [0] => string(1) "b" [1] => int(0) } } [1] => array(1) { [0] => array(2) { [0] => string(0) "" [1] => int(-1) } } [2] => array(1) { [0] => array(2) { [0] => string(1) "b" [1] => int(0) } } [3] => array(1) { [0] => string(0) "" } } As you can see, the third optional capture group returns something different than the first optional capture group. This is too a bug. Again, I don't care what representation is chosen. But it must be the same for any optional capture no matter if trailing or not.