With a global regex (which is used by preg_match_all ), after matching, the regex mechanism continues to search for the line from the end of the previous match.
In your case, the regex engine starts at the beginning of the line and advances to 0 , as this is the first character that matches [0-9] . Then he moves on to the next position ( 9 ), and since this corresponds to the second [0-9] , she takes 09 as a coincidence. When the engine continues to match (since it has not yet reached the end of the line), it again advances its position (to 1 ) (and then repeats above).
See also: First, see how the regex engine works
If you need to get every two-digit sequence, you can use preg_match and use offsets to determine where to start recording:
$fileName = 'A_DATED_FILE_091410.txt'; $allSequences = array(); $matches = array(); $offset = 0; while (preg_match('/[0-9][0-9]/', $fileName, $matches, PREG_OFFSET_CAPTURE, $offset)) { list($match, $offset) = $matches[0]; $allSequences[] = $match; $offset++;
Note that the offset returned with the PREG_OFFSET_CAPTURE flag is the beginning of a match.
I have another solution that will get five matches without using offsets, but I add it here only for curiosity, and I probably did not use it myself in the production code (this is a somewhat complicated regular expression too). You can use the regular expression that lookbehind uses to look up the number before the current position, and fix the number in lookbehind (in general, search queries are not captured):
(?<=([0-9]))[0-9]
Skip this regex:
(?<=
Since the reverse sides are zero width and do not move the position of the regular expression, this regular expression will correspond 5 times: the engine will advance to 9 (because this is the first position that satisfies the lookbehind statement). Since 9 matches [0-9], the engine will accept 9 as a match (but because we capture the search, it will also capture 0 !). Then the engine moves to 1 . Again, lookbehind succeeds (and captures), and 1 added as the 1st subgroup (and so on, until the engine reaches the end of the line).
When we give this preg_match_all template, we get an array that looks like (using the PREG_SET_ORDER flag to group capture groups together with a complete match):
Array ( [0] => Array ( [0] => 9 [1] => 0 ) [1] => Array ( [0] => 1 [1] => 9 ) [2] => Array ( [0] => 4 [1] => 1 ) [3] => Array ( [0] => 1 [1] => 4 ) [4] => Array ( [0] => 0 [1] => 1 ) )
Please note that each βmatchβ has its numbers out of order! This is because the capture group in lookbehind becomes backreference 1, while the entire match is backreference 0. We can return it together in the correct order, though:
preg_match_all('/(?<=([0-9]))[0-9]/', $fileName, $matches, PREG_SET_ORDER); $allSequences = array(); foreach ($matches as $match) { $allSequences[] = $match[1] . $match[0]; }