【问题标题】:named groups in PHP pcre regexPHP pcre 正则表达式中的命名组
【发布时间】:2011-10-21 17:35:59
【问题描述】:

尝试像这样匹配字符串:

/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 或永久链接?

【问题讨论】:

  • ...因为 id 段是空的?
  • 我以为我用 |获取 id 或永久链接。如果永久链接匹配 - 根本不应该存在任何 id。或者这不是垂直条的工作原理?

标签: php regex pcre


【解决方案1】:

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

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

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

要比较的字符串是abcdef,在某些情况下,您想知道两个子表达式都匹配,因此应该设置两个变量。如果在 some 情况下设置了这两个变量,最好在 all 情况下设置它们,这样程序员就不必首先检查它们之前是否已设置处理它们。

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

【讨论】:

    【解决方案2】:

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

    您可能还想稍微改进一下正则表达式,将&lt;permalink&gt; 中的. 替换为[^/],因为您不希望将尾部斜杠(如果存在)作为永久链接的一部分。

    不过,正如 Mob 所说,有一种更简单的方法可以解析这样一个简单的目标:

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

    【讨论】:

    • 感谢 [^/] 的提示。你的回答很好,但 Juhana 有点快,我只能选择一个接受的答案。
    【解决方案3】:

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

            $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
    )
    

    【讨论】:

    • 在这个例子中确实如此 - 但我将它用于各种路由,在这些路由中,可以方便地将正则表达式本身中的段名称指定为命名组。
    猜你喜欢
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多