我有以下正则表达式:
/xxx ([a-z]+)(?:, ([a-z]+))* xxx/
我想捕获以下测试字符串中的所有颜色:
xxx red, blue, pink, purple xxx
(现在只捕获红色和紫色)
打开此网址并查看匹配的群组:http://www.regex101.com/r/oZ2cH4
我已阅读以下http://www.regular-expressions.info/captureall.html但该技巧无效
(或者我做错了)
我该如何解决这个问题?
提前谢谢
答案 0 :(得分:3)
您可能希望根据以前的模式匹配返回匹配组:
$word = '[a-z]+';
$sep = '[, ]+';
$words = $captures("~($word)(?:{$sep})?~");
$of = $captures("~xxx ({$word}(?:{$sep}{$word})*) xxx~");
print_r($words($of($subject)));
输出:
Array
(
[0] => red
[1] => blue
[2] => pink
[3] => purple
)
$captures
是一个函数,它返回一个预配置的preg_match_all
调用,不仅可以处理作为主题的字符串,还可以处理foreach
可以操作的任何字符串:
$captures = function ($pattern, $group = 1) {
return function ($subject) use ($pattern, $group) {
if (is_string($subject)) {
$subject = (array)$subject;
}
$captures = [];
foreach ($subject as $step) {
preg_match_all($pattern, $step, $matches);
$captures = array_merge($captures, $matches[$group]);
}
return $captures;
};
};
默认情况下,如上例所示,它返回第一个组(1),但可以配置它。
这允许首先匹配外部模式($of
),然后在每个匹配上匹配内部模式($words
)。完整的例子:
$subject = '/xxx red, blue, pink, purple xxx/';
$captures = function ($pattern, $group = 1) {
return function ($subject) use ($pattern, $group) {
if (is_string($subject)) {
$subject = (array)$subject;
}
$captures = [];
foreach ($subject as $step) {
preg_match_all($pattern, $step, $matches);
$captures = array_merge($captures, $matches[$group]);
}
return $captures;
};
};
$word = '[a-z]+';
$sep = '[, ]+';
$seq = "";
$words = $captures("~($word)(?:{$sep})?~");
$of = $captures("~xxx ({$word}(?:{$sep}{$word})*) xxx~");
print_r($words($of($subject)));
请参阅live-demo。
答案 1 :(得分:0)
教程"Repeating a Capturing Group vs. Capturing a Repeated Group" (by regular-expressions.info)描述了如何在单次捕获中捕获所有内容“红色,蓝色,粉红色,紫色”。它建议的模式是
/xxx ((?:[a-z]+(?:, )?)+) xxx/
但如果这是你想要完成的,你也可以使用更简单的表达式
/xxx ([a-z, ]*) xxx/
我怀疑你真正想要的是分别捕捉每种颜色。这可能最好通过捕获整个列表一次,然后解析捕获的内容。