正则表达式量化捕获

时间:2012-03-14 14:24:07

标签: php regex

php > preg_match("@/m(/[^/]+)+/t/?@", "/m/part/other-part/t", $m);
php > var_dump($m);
array(2) {
  [0]=>
  string(20) "/m/part/other-part/t"
  [1]=>
  string(11) "/other-part"
}
php > preg_match_all("@/m(/[^/]+)+/t/?@", "/m/part/other-part/t", $m);
php > var_dump($m);
array(2) {
  [0]=>
  array(1) {
    [0]=>
    string(20) "/m/part/other-part/t"
  }
  [1]=>
  array(1) {
    [0]=>
    string(11) "/other-part"
  }
}

通过上述示例,我希望捕获与/part/other-part匹配,遗憾的是,正则表达式/m(/[^/]+)+/t/?并未像我预期的那样捕获这两者。

此捕获不应仅限于匹配此样本,它应捕获捕获组的未定义重复次数;例如/m/part/other-part/and-another/more/t

更新 鉴于这是预期的行为,我的问题就是如何实现我的匹配?

3 个答案:

答案 0 :(得分:2)

这就是捕捉群体的方式。重复捕获组只有在正则表达式完成后存储的最后一个匹配。那是你的测试“/ other-part”。

试试这个

/m((?:/[^/]+)+)/t/?

看到它here on Regexr,将鼠标悬停在匹配项上时,您可以看到捕获组的内容。

只需在开始时添加?:并在整个重复过程中添加另一个,即可使您的群组无法捕获。

在php中

preg_match_all("@/m((?:/[^/]+)+)/t/?@", "/m/part/other-part/t", $m);
var_dump($m);

输出:

array(2) { 
    [0]=> array(1) { 
        [0]=> 
        string(20) "/m/part/other-part/t" 
    }
    [1]=> array(1) { 
        [0]=> 
        string(16) "/part/other-part" 
    }
}

答案 1 :(得分:2)

试试这个:

preg_match_all("@(?:/m)?/([^/]+)(?:/t)?@", "/m/part/other-part/another-part/t", $m);
var_dump($m);

它给出了:

array(2) {
  [0]=>
  array(3) {
    [0]=>
    string(7) "/m/part"
    [1]=>
    string(11) "/other-part"
    [2]=>
    string(15) "/another-part/t"
  }
  [1]=>
  array(3) {
    [0]=>
    string(4) "part"
    [1]=>
    string(10) "other-part"
    [2]=>
    string(12) "another-part"
  }
}

//编辑

IMO做你想做的事情的最好方法是使用 @stema 中的preg_match()并按/分解结果以获得你想要的部分列表。

答案 2 :(得分:0)

正如评论中已经写过的那样,你不能一次做到这一点,因为preg_match不允许你返回相同的子组匹配(就像你可以用Javascript或.Net做的那样,见 Get repeated matches with preg_match_all() 的)。因此,您可以将操作分为多个步骤:

  1. 匹配主题,提取您感兴趣的部分。
  2. 仅匹配感兴趣的部分。
  3. 代码:

    $subject = '/m/part/other-part/t';
    $subpattern = '/[^/]+';
    $pattern = sprintf('~/m(?<path>(?:%s)+)/t/?~', $subpattern);
    $r = preg_match($pattern, $subject, $matches);
    if (!$r) return;
    $r = preg_match_all("~$subpattern~", $matches['path'], $matches);
    var_dump($matches);
    

    输出:

    array(1) {
      [0]=>
      array(2) {
        [0]=>
        string(5) "/part"
        [1]=>
        string(11) "/other-part"
      }
    }