Как определить, были ли названные группы PREG использованы в шаблоне, переданном в preg_match ()? - PullRequest
3 голосов
/ 09 декабря 2010

Мне интересно определить, использовались ли именованные группы в шаблоне, передаваемом в preg_match ().

Представьте себе сценарий, в котором список шаблонов регулярных выражений повторяется и передается в preg_match ().Что-то вроде следующего:

$trg = "123abc/4";
$patterns = array('/abc/', '/abc\/(\d+)/', '/abc\/(?P<id>\d+)/');
foreach ($patterns as $p) {
   preg_match($p, $trg, $matches);
   if (len($matches) > 0) {
      // Do something interesting with the capture
   } 
}

Если совпадение найдено, то в $ совпадений будет хотя бы один элемент.Два последних шаблона содержат перехват, но $ match будет массивом из двух элементов в первом случае и массивом из трех элементов в последнем.используемый.Мне нужно это знать, потому что я хочу передать захваченный текст другим функциям.

Как вы можете себе представить, шаблоны будут известны только во время выполнения, поэтому я не могу просто посмотреть на количество элементовв матче.

Любые идеи о том, как решить эту проблему?

Спасибо за ваше время.

Ответы [ 4 ]

0 голосов
/ 10 июня 2019

Вы также можете использовать T-Regx облегченную библиотеку с Match:

$match->namedGroups();
0 голосов
/ 09 декабря 2010

Вы можете проверить, используя array_keys, наличие нецифровых ключей, которые будут указывать на наличие именованного совпадения.

0 голосов
/ 12 декабря 2010

А как насчет пользовательской функции is_assoc? Поскольку PHP не различает списки и хэши, я нашел это полезным и для нескольких других случаев.

<?php
function is_assoc(&$arr) {
    return array_keys($arr) !== range(0, count($arr) - 1);
}
if (preg_match('/(?P<foo>foo)/', 'foo', $match) && is_assoc($match)) {
    echo "yep, it had named groups";
}

В нем отсутствует «чистота» наличия функции для этой цели в стандартной библиотеке PHP (о которой я знаю), но фактический оператор if все еще очень компактен и удобочитаем.

Я знаю, что ваш пример, вероятно, представляет лишь небольшую часть вашей программы, но мне кажется, что все шаблоны написаны вами вручную и существуют в коде, поэтому вы всегда знаете, какие из них будут возвращать именованные группы, потому что вы поместите названные группы там. Не могли бы вы просто изменить foreach ($patterns as $p) на foreach ($patterns as $i=>$p) и проверить значение $i, когда совпадение найдено?

0 голосов
/ 09 декабря 2010

Это будет в ключе массива совпадений, если использовалась именованная группа.

Массив
(
[0] => abc / 4
[id] => 4
[1] => 4
)

...