Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use previous backreference as name of named capture group

Is there a way to use a backreference to a previous capture group as the name of a named capture group? This may not be possible, if not, then that is a valid answer.

The following:

$data = 'description: some description';
preg_match("/([^:]+): (.*)/", $data, $matches);
print_r($matches);

Yields:

(
    [0] => description: some description
    [1] => description
    [2] => some description
)

My attempt using a backreference to the first capture group as a named capture group (?<$1>.*) tells me it's either not possible or I'm just not doing it correctly:

preg_match("/([^:]+): (?<$1>.*)/", $data, $matches);

Yields:

Warning: preg_match(): Compilation failed: unrecognized character after (?< at offset 12

The desired result would be:

(
    [0] => description: some description
    [1] => description
    [description] => some description
)

This is simplified using preg_match. When using preg_match_all I normally use:

$matches = array_combine($matches[1], $matches[2]);

But thought I might be slicker than that.

like image 376
AbraCadaver Avatar asked Jan 29 '23 16:01

AbraCadaver


2 Answers

In short, it is not possible, you can stick to the programming means you have been using so far.

Group names (that should consist of up to 32 alphanumeric characters and underscores, but must start with a non-digit) are parsed at compile time, and a backreference value is only known at run-time. Note it is also a reason why you cannot use a backreference inside a lookbehind (altghough you clearly see that /(x)y[a-z](?<!\1)/ is OK, the PCRE regex engine sees otherwise as it cannot infer the length of the lookbehind with a backreference).

like image 152
Wiktor Stribiżew Avatar answered Jan 31 '23 06:01

Wiktor Stribiżew


You already have an answer to the regex question (no), but for a different PHP based approach you could try using a callback.

preg_replace_callback($pattern, function($match) use (&$matches) {
    $matches[$match[1]] = $match[2];
}, $data);
like image 26
Don't Panic Avatar answered Jan 31 '23 04:01

Don't Panic