kvway
kvway

Reputation: 494

Two groups with the same name in the php regex

I have an input which contains substring in the format of TXT number or number TXT. I would like to write regexp which will match the format and returns only the number.

I came up with something like this:

$regex = '/TXT(?<number>[0-9]+)|(?<number>[0-9]+)TXT/'

The problem is that the compiler says that group with name number is already defined even though there is or operator in between.

Is it possible in php to write 2 groups with the same name? If it is not then how can I write regexp like that?

Upvotes: 3

Views: 404

Answers (2)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626738

To write 2 groups with the same name you need to use the (?J) inline flag:

'/(?J)TXT(?<number>[0-9]+)|(?<number>[0-9]+)TXT/'

See the regex demo

Documentation:

J (PCRE_INFO_JCHANGED)
The (?J) internal option setting changes the local PCRE_DUPNAMES option. Allow duplicate names for subpatterns. As of PHP 7.2.0 J is supported as modifier as well.

PHP demo:

$regex = '/(?J)TXT(?<number>[0-9]+)|(?<number>[0-9]+)TXT/';
if (preg_match_all($regex, "TXT123 and 456TXT1", $matches, PREG_SET_ORDER, 0)) {
    foreach ($matches as $m) {
        echo $m["number"] . PHP_EOL;
    }
}

Note that in your case, you do not need the groups:

'/TXT\K[0-9]+|[0-9]+(?=TXT)/'

The lookarounds will also do the job here.

Upvotes: 5

The fourth bird
The fourth bird

Reputation: 163217

You could use a branch reset group (?| and add a space between the digits and the TXT.

(?|TXT (?<number>[[0-9]+)|(?<number>[[0-9]+) TXT)

Regex demo | Php demo

For example

$re = '/(?|TXT (?<number>[[0-9]+)|(?<number>[[0-9]+) TXT)/';
$str = 'TXT 4
4 TXT';

preg_match_all($re, $str, $matches);
print_r($matches["number"]);

Output

Array
(
    [0] => 4
    [1] => 4
)

Upvotes: 1

Related Questions