【问题标题】:How to tell if PREG named groups were used in the pattern passed to preg_match()?如何判断 PREG 命名组是否在传递给 preg_match() 的模式中使用?
【发布时间】:2019-06-19 20:57:46
【问题描述】:

我有兴趣确定是否在传递给 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
   } 
}

如果找到匹配项,则 $matches 中将至少有一个元素。两个最终模式包含一个捕获,但 $matches 在第一种情况下将是一个二元素数组,并且 最后一个三元素数组。

我想知道是否使用了命名组,而不用 grep 模式。我需要知道这一点,因为我想将捕获的文本传递给其他函数。

您可以想象,模式要到运行时才能知道,所以我不能简单地查看匹配中的元素数量。

关于如何解决这个问题的任何想法?

感谢您的宝贵时间。

【问题讨论】:

    标签: php preg-match


    【解决方案1】:

    自定义 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=&gt;$p) 并在找到匹配项时检查$i 的值吗?

    【讨论】:

    • 感谢您的代码。我认为可悲的事实是,在这种情况下,PHP 的功能有点不足,需要一点点掌握。伊克。
    • 我有一个文件,里面装满了我总是包含的小助手函数。没有它,我最终会感到有点失落。
    【解决方案2】:

    如果使用了命名组,它将在匹配数组的键中。

    数组
    (
    [0] => abc/4
    [id] => 4
    [1] => 4
    )

    【讨论】:

      【解决方案3】:

      您可以使用array_keys 检查是否存在非数字键,这表明存在命名匹配。

      【讨论】:

      • 我相信这种方法会奏效。我希望有一个更清洁的解决方案。
      【解决方案4】:

      您还可以将T-Regx 轻量级库与Match 一起使用:

      $match->namedGroups();
      

      【讨论】:

        猜你喜欢
        • 2021-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-21
        相关资源
        最近更新 更多