重复捕获正则表达式

时间:2019-02-10 22:56:33

标签: php regex pcre

我一直在尝试使此Regex正常工作,但我感觉自己已经快用完了,但是我不确定如何获得所需的结果。我正在使用类似于JSON对象的模拟数据结构,并试图解析参数。

结构类似于以下组和选项:group_label:id{option_1:id,option_2:id ... }

到目前为止,我想出的表情是

(?:(?:(?<group_name>[a-zA-Z0-9 _]+?):(?<group_id>[0-9]+?){(?:(?:(?<option_name>.+?):(?<option_id>.+?))+?,?)+?},?))+?

我正在使用的测试数据为:

My Interests:379{Commercial:0,Consumer:1,Wholesale Reseller:2},Test Group:1234{Test One:1,Test 2:2}

这里是指向我正在查看的正则表达式测试器的链接,您可以看到每个组都变成了一个匹配项,但是它仅捕获了每个选项的最后一个,在这里我想为所有选项。

https://regex101.com/r/GkW57Y/1

如果我尝试指定字符串的开头和结尾,它也会中断,因此我敢肯定,这提示我正在做的事情是错误的,但是我不是正则表达式专家,所以我米准时运行时间较短。与往常一样,任何建议总是倍受赞赏!

1 个答案:

答案 0 :(得分:0)

这里是一个正则表达式,可以通过查找不同功能来提取组和选项(组以{结尾,选项以{,开头并以{{1结尾}}或,):

}

在PHP中,您可以像这样使用它来获取(?<group_name>[a-zA-Z0-9 _]+):(?<group_id>[0-9]+)(?={)|(?<=[{,])(?<option_name>[^:]+):(?<option_id>[^,}]+)(?=[,}]) groups的列表:

options

输出:

$string = 'My Interests:379{Commercial:0,Consumer:1,Wholesale Reseller:2},Test Group:1234{Test One:1,Test 2:2}';
$regex = '(?<group_name>[a-zA-Z0-9 _]+):(?<group_id>[0-9]+)(?={)|(?<=[{,])(?<option_name>[^:]+):(?<option_id>[^,}]+)(?=[,}])';
preg_match_all("/$regex/", $string, $matches);
//print_r($matches);
$groups = array_combine(array_filter($matches['group_name']), array_filter($matches['group_id'], function ($v) { return $v !== '';}));
$options = array_combine(array_filter($matches['option_name']), array_filter($matches['option_id'], function ($v) { return $v !== '';}));
print_r($groups);
print_r($options);

如果您需要更结构化的输出,则可以在获得匹配项后执行以下操作:

Array (
    [My Interests] => 379
    [Test Group] => 1234
)
Array (
    [Commercial] => 0
    [Consumer] => 1
    [Wholesale Reseller] => 2
    [Test One] => 1
    [Test 2] => 2 
)

输出:

$output = array();
for ($i = 0; $i < count($matches['group_name']); $i++) {
    if ($matches['group_name'][$i] != '') {
        // new group
        $this_group = $matches['group_name'][$i];
        $output[$this_group] = array('id' => $matches['group_id'][$i]);
    }
    else {
        // option for this group
        $output[$this_group]['options'][$matches['option_name'][$i]] = $matches['option_id'][$i];
    }
}
print_r($output);

或者可能更有用:

Array (
    [My Interests] => Array (
        [id] => 379
        [options] => Array (
            [Commercial] => 0
            [Consumer] => 1
            [Wholesale Reseller] => 2
        )
    )
    [Test Group] => Array (
        [id] => 1234
        [options] => Array (
            [Test One] => 1
            [Test 2] => 2
         )
    ) 
)

输出:

$output = array();
$this_group = -1;
for ($i = 0; $i < count($matches['group_name']); $i++) {
    if ($matches['group_name'][$i] != '') {
        // new group
        $this_group++;
        $output[$this_group] = array('name' => $matches['group_name'][$i], 'id' => $matches['group_id'][$i]);
    }
    else {
        // option for this group
        $output[$this_group]['options'][$matches['option_name'][$i]] = $matches['option_id'][$i];
    }
}
print_r($output);

Demo on 3v4l.org