Две группы с одинаковым именем в регулярном выражении php - PullRequest
3 голосов
/ 17 октября 2019

У меня есть вход, который содержит подстроку в формате TXT number или number TXT. Я хотел бы написать регулярное выражение, которое будет соответствовать формату и возвращает только число.

Я придумал что-то вроде этого:

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

Проблема в том, чтокомпилятор говорит, что группа с именем number уже определена, хотя между ними есть оператор или.

Возможно ли в php написать 2 группы с одинаковым именем? Если это не так, то как я могу написать регулярное выражение, как это?

Ответы [ 2 ]

4 голосов
/ 17 октября 2019

Чтобы написать 2 группы с одинаковыми именами, необходимо использовать встроенный флаг (?J):

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

См. Демонстрационную версию regex

Документация :

J (PCRE_INFO_JCHANGED)Внутренний параметр (?J) изменяет локальный параметр PCRE_DUPNAMES. Разрешить повторяющиеся имена для подшаблонов. Начиная с версии PHP 7.2.0 J также поддерживается как модификатор.

Демонстрация PHP :

$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;
    }
}

Обратите внимание, что вв вашем случае вам не нужны группы:

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

Lookarounds также сделают эту работу здесь.

1 голос
/ 17 октября 2019

Вы можете использовать группу сброса ветвей (?| и добавить пробел между цифрами и TXT.

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

Regex demo | Php demo

Например

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

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

Выход

Array
(
    [0] => 4
    [1] => 4
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...