1

我有以下正则表达式:

/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但技巧没有奏效

(或者也许我做错了)

我该如何解决这个问题?

先感谢您

4

2 回答 2

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)));

现场演示

于 2013-05-12T09:28:38.257 回答
0

教程“重复捕获组与捕获重复组”(由 regular-expressions.info 提供)描述了如何在一次捕获中捕获所有内容“红色、蓝色、粉红色、紫色”。它建议的模式是

/xxx ((?:[a-z]+(?:, )?)+) xxx/

但如果这真的是你想要完成的,你不妨使用更简单的表达

/xxx ([a-z, ]*) xxx/

我怀疑您真正想要的是单独捕获每种颜色。这可能最好通过捕获整个列表一次,然后解析捕获的内容来完成。

于 2013-05-12T05:03:54.607 回答