Reputation: 494
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
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
J (PCRE_INFO_JCHANGED)
The(?J)
internal option setting changes the localPCRE_DUPNAMES
option. Allow duplicate names for subpatterns. As of PHP 7.2.0 J is supported as modifier as well.
$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
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)
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