Named Capturing Groups in PHP Regex
Let's say we want to use preg_match
to
split a date into day, month, and year. We'll use
capturing groups for this:
<?php
$str = '2025-10-29';
$reg = '#(\d{4})-(\d{2})-(\d{2})#';
preg_match($reg, $str, $match);
var_dump($match); // will output ['2025-10-29', '2025', '10', '29']
?>
As you can see, the result is an array where the zeroth element contains the entire date, the first - the year, the second - the month, the third - the day.
However, sometimes it would be convenient to get the contents of the capturing groups as an associative array. That is, in our case, it would be nice to get an array like this:
[
'year' => '2025',
'month' => '10',
'day' => '29'
]
For this, there is a special syntax
in regular expressions. Here it is: (?<name>pattern)
,
where pattern
is the regex pattern, and name
is the name of the capturing group.
Let's rewrite our date regex using named capturing groups:
<?php
$str = '2025-10-29';
$reg = '#(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})#';
preg_match($reg, $str, $match);
var_dump($match);
?>
As a result, we will get an associative array where the keys will be the names of the capturing groups, and the values will be what was captured in them:
[
'year' => '2025',
'month' => '10',
'day' => '29',
]
Actually, in the result array, the values
of the capturing groups will be accessible both by name and
by sequential number. That is, for example,
the year will be accessible by the key 'year'
and by number 1
, the month - by key 'month'
and by number 2
, and so on:
[
'year' => '2025',
'month' => '10',
'day' => '29',
1 => '2025',
2 => '10',
3 => '29'
]
The described named capturing groups have a few more
alternative syntaxes: (?P<name>pattern)
and (?'name'pattern)
.
Given a string with time:
<?php
$str = '12:59:59';
?>
Place the hours, minutes, and seconds into separate named capturing groups.
Write a function that, in the result array, removes all numbered capturing groups, leaving only the named ones.