首页 > 解决方案 > 重复捕获正则表达式

问题描述

我一直试图让这个 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

如果我尝试指定字符串的开头和结尾,它也会中断,所以我确信这暗示我正在做的事情是错误的,但我不是正则表达式专家,而且我跑得更短准时。与往常一样,任何建议都将不胜感激!

标签: phpregexpcre

解决方案


这是一个正则表达式,它将通过查找不同的特征来提取组和选项(组以 结尾{,选项以 or 开头并以or{结尾,):,}

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

在 PHP 中,您可以像这样使用它来获取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);

输出:

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

3v4l.org 上的演示


推荐阅读