假设我有以下字符串:
[
我需要捕获以下字符串:
printf
$string = 'cats[Garfield,Tom,Azrael]';
cats
Garfield
该字符串可以是任何类似文字的文本,后面是括号,其中包含逗号分隔的类似字的条目列表。我尝试了以下方法:
Tom
问题是Azrael
忽略preg_match('#^(\w+)\[(\w+)(?:,(\w+))*\]$#', $string, $matches);
,只匹配第一只猫和最后一只猫。
现在,我知道如何通过更多调用来实现这一点,可能会将$matches
和Tom
结合起来,所以问题是不一般如何做。
问题是:可以用单preg_match()
来完成,所以我可以一次验证和匹配吗?
答案 0 :(得分:2)
基本问题似乎是:是否可以提取重复捕获组的每次出现?
答案是否定的。
但是,存在几种解决方法:
最容易理解的是使用两个步骤:捕获完整列表然后拆分它。类似的东西:
$str = 'cats[Garfield,Tom,Azrael,Supermatou]';
if ( preg_match('~(?<item>\w+)\[(?<list>\w+(?:,\w+)*)]~', $str, $m) )
$result = [ $m['item'], explode(',', $m['list']) ];
(或您想要的任何结构)
其他解决方法将preg_match_all
与\G
锚点结合使用,该锚点匹配字符串的开头或成功匹配后的位置:
$pattern = '~(?:\G(?!\A),|(?<item>\w+)\[(?=[\w,]+]))(?<elt>\w+)~';
if ( preg_match_all($pattern, $str, $matches) )
print_r($matches);
此设计确保所有元素都在括号之间。
要获得更多 flat 结果,您还可以这样写:
$pattern = '~\G(?!\A)[[,]\K\w+|\w+(?=\[[\w,]+])~';
最后一个模式的细节:
~
# first alternative (can't be the first match)
\G (?!\A) # position after the last successful match
# (the negative lookahead discards the start of the string)
[[,] # an opening bracket or a comma
\K # return the whole match from this position
\w+ # an element
| # OR
# second alternative (the first match)
\w+ # the item
(?= # lookahead to check forward if the format is correct
\[ # opening bracket
[\w,]+ # word characters and comma (feel free to be more descriptive
# like \w+(?:,\w+)* or anything you want)
] # closing bracket
)
~
答案 1 :(得分:0)
为什么不是简单的preg_match_all:
$string = 'cats[Garfield,Tom,Azrael], entity1[child11,child12,child13], entity2:child21&child22&child23';
preg_match_all('#\w+#', $string, $matches);
print_r($matches);
<强>输出:强>
Array
(
[0] => Array
(
[0] => cats
[1] => Garfield
[2] => Tom
[3] => Azrael
[4] => entity1
[5] => child11
[6] => child12
[7] => child13
[8] => entity2
[9] => child21
[10] => child22
[11] => child23
)
)