2010-12-09 22 views
3

我有兴趣确定在传递给preg_match()的模式中是否使用了命名组。如何判断在传递给preg_match()的模式中是否使用了PREG命名组?

想象一下,将正则表达式模式列表迭代并传递到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中将至少有一个元素。两个最终模式包含一个捕获,但$匹配将是第一种情况下的两个元素数组,最后一个是三元素数组。

我想知道,如果使用命名组,则不会使用模式。我需要知道这一点,因为我想将捕获的文本传递给其他函数。你可以想象,模式直到运行时才会被知道,所以我不能简单地看看匹配中的元素数量。

有关如何解决此问题的任何想法?

谢谢你的时间。

回答

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=>$p)并检查匹配时发现$i的值?

+0

感谢您的代码。我认为令人遗憾的事实是,在这种情况下,PHP有点不足,需要一些手持。伊克。 – jjohn 2010-12-13 14:44:22

1

如果使用了一个命名组,它将位于matches数组的关键字中。

阵列

[0] => ABC/4
[ID] => 4
[1] => 4

1

你可以检查,使用array_keys,是否非 - 存在数字键,这表示存在指定的匹配。

+0

我相信这种方法可行。我希望有一个更清洁的解决方案。 – jjohn 2010-12-09 17:07:22

相关问题