2012-03-14 129 views
4
php > preg_match("@/m(/[^/]+)+/t/[email protected]", "/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/[email protected]", "/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

UPDATE: 鉴于这是预期的行为,我的问题代表作为我将如何能够实现我的这个匹配?

+1

我预计是由于量词反复应用的捕获组'+' – mhitza 2012-03-14 14:28:49

+0

也“不工作”是不是好有一个问题标题。实际上,量化器确实如PCRE中所公布的那样工作。 – hakre 2012-03-14 14:31:37

+0

@hakre从标题中删除了不工作的部分。根据你的回答,我的记忆似乎在欺骗我,因为我记得对捕捉组进行了量化。 – mhitza 2012-03-14 14:33:57

回答

2

试试这个:

preg_match_all("@(?:/m)?/([^/]+)(?:/t)[email protected]", "/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" 
    } 
} 

//编辑

国际海事组织做你想做的是从@stema使用的preg_match()和爆炸由/导致得到你想要的部分名单的最佳途径。已经写在注释

+0

'/ m'开头是否可选?我明白你为什么这样做,但这不是不准确吗? – hakre 2012-03-14 14:46:59

+0

是的,它是不精确的,但如果它不是可选的,正则表达式不能爆炸他想要的部分。我会用简单的'preg_match()'+'explode()'来获得他想要的部分。 – piotrekkr 2012-03-14 14:52:19

+0

@piotrekkr你的回答更符合问题(我会接受它);但是我会使用stema的响应,而不是在preg_match()和爆炸而不是这个严格的预检中,如果字符串以(/ m)开头并以(/ t /?)结尾:) – mhitza 2012-03-14 14:56:18

2

这就是捕捉小组的工作方式。重复捕获组只有在正则表达式完成后才存储最后的匹配。多数民众赞成在你的测试“/其他部分”。

试试这个

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

看到它here on Regexr,而悬停在比赛,你可以看到捕获组的内容。

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

在PHP

preg_match_all("@/m((?:/[^/]+)+)/t/[email protected]", "/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" 
    } 
} 
+0

请参阅我更新的问题。因为如果是这样,我仍然想知道如何实现这一点。 – mhitza 2012-03-14 14:36:48

+0

@mhitza已经更新了我的答案。 – stema 2012-03-14 14:37:16

0

如,你不能这样做一次,因为preg_match不允许返回相同亚型匹配,以及(如你可以用JavaScript或.Net做,看到Get repeated matches with preg_match_all())。所以,你可以把操作到多个步骤:

  1. 匹配的主题,提取你感兴趣的部分
  2. 仅匹配感兴趣的部分。

代码:

$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" 
    } 
}