⊗ppPmRgCPN 257 of 447 menu

Common Number of Capture Groups in PHP Regex

Consider the following situation. Suppose we have a variable with a year that can range from 1990 to 2099. Let's say we want to get the last two digits of the year into a capture group. Let's write the corresponding regex:

<?php $reg = '#19(9\d)|20(\d\d)#'; ?>

However, there is one inconvenience awaiting us here. The fact is that for years of the last century, the two digits will go into the first capture group, while for years of the second century - into the second one. Let's look at some examples.

Here is the first option:

<?php $str = '1991'; preg_match($reg, $str, $res); var_dump($res); // [1 => '91'] ?>

And here is the second option:

<?php $str = '2021'; preg_match($reg, $str, $res); var_dump($res); // [2 => '21'] ?>

Now suppose we want to write the found year digits into a variable. We face a problem, because we don't know exactly which key to use to get the data from the capture group:

<?php $year = $res[1]; // we need key either 1 or 2 ?>

The problem can be solved with a condition:

<?php if (!empty($res[1])){ $year = $res[1]; } else{ $year = $res[2]; } ?>

However, there is a simpler solution. You can use a special command (?| ). All capture groups inside it will have the same number.

Let's fix our regex

<?php $reg = '#(?|19(9\d)|20(\d\d))#'; ?>

And now our year will definitely be in the capture group with number one:

<?php $year = $res[1]; ?>

Given strings with dates, where the year can range from 1990 to 2099:

<?php $arr = [ '31-12-2025', '30-11-1995', '29-10-1990', ]; ?>

For each date, put the day in the first capture group, the month in the second, and the last two digits of the year - in the third.

byenru