我有以下regexp:
/(?:['['{]*)(?:([A-G'-][^A-G']'}]*)+)(?:[']'}]*)/
与以下表达式:
{A''BsCb}
我期待3个匹配的结果
A''
Bs
Cb
但是在https://regex101.com/上测试只给我最后一次匹配Cb
,并告诉我重复捕获组只捕获最后一次迭代,在重复组周围放置捕获组。
我想那就是我所做的!我以为我已经理解了这里所描述的问题http://www.regular-expressions.info/captureall.html因此,我的+外面有括号,里面有捕获组。
但是要么太迟了,要么我需要一个人的头不会在提到regexp时崩溃,告诉我我错在哪里。
您可以在项目0处使用preg_match_all
的模式获得它:
~
(?:
'G (?!'A) # contiguous to previous match, but not at the start of the string
|
{ (?=[^}]* }) # start with { and check if a closing bracket follows
|
'[ (?=[^]]* ]) # the same for square bracket
)
'K # start the match result here
[A-G] [^]A-G}]*
~xS
演示您正在尝试匹配重复的捕获组并获得捕获。这是不可能的PHP PCRE regex。
您可以做的是确保您提取所有{...}
/[...]
子字符串,从括号中修剪它们并使用简单的[A-G-][^A-G]*
regex,或添加'G
操作符,使您的regex不可维护,但工作为原始的。
解1为
/(?:[[{]*|(?!'A)'G)'K[A-G-][^A-G']}]*/
参见regex演示。注意:这个正则表达式不检查关闭的]
或}
,但它可以添加一个正向前看。
-
(?:[[{]*|(?!'A)'G)
-匹配[
或{
,零个或多个出现,或前一次成功匹配的结束位置 -
'K
-省略目前匹配的文本 -
[A-G-]
-A
到G
的字母和-
-
[^A-G']}]*
-除A
到G
以及]
和}
以外的零个或多个字符。
参见PHP演示。
解2为
$re = '/(?|{([^}]*)}|'[([^]]*)])/';
$str = "{A''BsCb}";
$res = array();
preg_match_all($re, $str, $m);
foreach ($m[1] as $match) {
preg_match_all('~[A-G-][^A-G]*~', $match, $tmp);
$res = array_merge($tmp, $res);
}
print_r($res);
查看PHP演示
(?|{([^}]*)}|'[([^]]*)])
正则表达式只匹配字符串,如{...}
或[...]
(但不是{...]
或[...}
),并捕获括号之间的内容到组1(因为分支重置组(?|...)
重置每个分支中的组id)。然后,我们所需要的就是用更连贯的'~[A-G-][^A-G]*~'
正则表达式抓取我们需要的内容。
你已经想明白了。关于@sln的评论,在PHP的正则表达式风格的PCRE中重复一个组时,没有办法在一个或不同的捕获组中收集每个单个匹配。在本例中,只捕获最后一个匹配项。
但是,如果断言在字符串的开始和结束处应该有大括号并不重要,并且您只需要这些值,则需要做的工作较少:
$array = array_filter(preg_split("~(?=[A-G])~", trim("{A''BsCb}", '[{}]')));
正则表达式:
(?=[A-G]) # Positive lookahead to find next character be one from character class
这个正则表达式将匹配所有相似的位置,以在split时输出正确的数据:
array(3) {
[1]=>
string(3) "A''"
[2]=>
string(2) "Bs"
[3]=>
string(2) "Cb"
}
现场演示