[英]regex not matching due to repeated capturing group rather than capturing a repeated group
我有以下正则表达式:
/(?:[\[\{]*)(?:([A-G\-][^A-G\]\}]*)+)(?:[\]\}]*)/
具有以下表达式:
{A''BsCb}
我希望有3个匹配结果
A''
Bs
Cb
但是在https://regex101.com/上进行的测试仅给我最后一次匹配Cb
,并告诉我重复捕获组将仅捕获最后一次迭代,将捕获组放在重复组周围。
我以为那是我所做的! 我以为我已经理解了这里描述的问题http://www.regular-expressions.info/captureall.html因此,在+括号内是捕获组。
但是,要么为时已晚,要么我需要一个不冒头的人来提及regexp来告诉我我哪里出问题了。
您可以通过preg_match_all
在项目0处以这种模式获得它:
~
(?:
\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正则表达式是不可能的。
您可以做的是确保提取所有{...}
/ [...]
子字符串,从括号中修剪掉它们,并使用简单的[AG-][^AG]*
正则表达式,或添加\\G
运算符,使您的正则表达式无法维护,但可以作为原始正则表达式工作。
解决方案1是
/(?:[[{]*|(?!\A)\G)\K[A-G-][^A-G\]}]*/
参见regex演示 。 注意:此正则表达式不检查结尾的]
或}
,但可以使用正向提前添加。
(?:[[{]*|(?!\\A)\\G)
-匹配[
或{
,出现零个或多个,或上一次成功匹配的结束位置 \\K
省略到目前为止匹配的文本 [AG-]
G
-
[AG-]
-从A
到G
字母和-
[^AG\\]}]*
-零个或多个从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)。 然后,我们所需要的只是使用更连贯的'~[AG-][^AG]*~'
正则表达式来获取我们所需要的东西。
您已经知道了。 关于@sln的评论,当在PCRE中重复一个PHP的正则表达式风格的组时,没有办法在一个或不同的捕获组中收集每个单个匹配项。 在这种情况下,仅捕获最后一个匹配项。
但是,如果断言在字符串的开头和结尾处都应有括号,则不重要,而您只需要这些值,那么要做的工作就更少了:
$array = array_filter(preg_split("~(?=[A-G])~", trim("{A''BsCb}", '[{}]')));
正则表达式:
(?=[A-G]) # Positive lookahead to find next character be one from character class
此正则表达式将匹配所有相似的位置以在拆分时输出正确的数据:
array(3) {
[1]=>
string(3) "A''"
[2]=>
string(2) "Bs"
[3]=>
string(2) "Cb"
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.