PHP pcre regex中的命名组

时间:2011-10-21 17:36:00

标签: php regex pcre

尝试匹配这样的字符串:

/2011/10/Lorem-ipsum-dolor-it-amet-consectetur-adipisicing
/2011/10/Lorem-ipsum-dolor-it-amet-consectetur-adipisicing/

/2011/10/4545
/2011/10/4545/

获得年,月和第三部分。这是我得到的正则表达式:

%/(?P<year>\d{4})/(?P<month>\d{2})/((?P<id>\d{1,})|(?P<permalink>.{1,}))[/]{0,1}$%

我虽然得到的匹配数组总是包含3个变量:年,月和id或永久链接。但是会发生什么 - 如果永久链接匹配 - 我仍然会在结果数组中获得空id变量。有没有办法重写一个正则表达式,所以结果数组只包含年,月,id或永久链接?

3 个答案:

答案 0 :(得分:4)

我认为使用|语法时,命名组不会被“忽略”,因为无法知道是否要保留两个结果。换句话说,|的两边都会被评估,即使其中一方有或没有匹配,与大多数编程语言中的条件or不同。

例如,如果你有一个正则表达式

/(?P<foo>abc)|(?P<bar>def)/

并且要比较的字符串是abcdef,在某些情况下,您希望知道两个子表达式匹配,因此应设置两个变量。如果在某些情况下设置了两个变量,最好在所有情况下设置它们,这样程序员就不必首先检查它们是否已经设置过处理它们。

作为对问题的评论“有没有办法重写正则表达式,因此生成的数组只包含年,月和id或永久链接”,为什么你想要这样?只需检查变量是否为空。如果正则表达式会将其中任何一个退出,您仍然需要检查它们中的哪一个已设置。完全相同的逻辑可用于检查哪些是空的。

答案 1 :(得分:1)

您不一定需要正则表达式。

        $x = "/2011/10/4545";
        $v = explode("/", $x);
        $r = array_shift($v);
        if(count($v) == 4){
             array_pop($v);
             print_r($v);    }

输出

Array
(
    [0] => 2011
    [1] => 10
    [2] => 4545

$url = "/2011/10/Lorem-ipsum-dolor-it-amet-consectetur-adipisicing";
    $v = explode("/", $url);
    array_shift($v);
    array_pop($v);
    if(count($v) == 3){
      array_pop($v);
    print_r($v);
} else {

print_r($v); }

输出

Array
(
    [0] => 2011
    [1] => 10
)

答案 2 :(得分:1)

由于它们存在于正则表达式中,因此命名组将始终包含在匹配组中,即使它们由于|而未匹配任何内容。

您可能还想稍微改进正则表达式,用.替换<permalink> [^/],因为您不希望使用尾部斜杠(如果存在)作为固定链接。

然而,正如Mob所说,有一种更简单的方法可以解析这么简单的目标:

list($year, $target, $link) = array_slice(explode('/', $url), 1);
if (is_numeric($link)) {
    // $link == id
}
else {
    // $link == permalink
}