php - 重复捕获正则表达式
问题描述
我一直试图让这个 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
如果我尝试指定字符串的开头和结尾,它也会中断,所以我确信这暗示我正在做的事情是错误的,但我不是正则表达式专家,而且我跑得更短准时。与往常一样,任何建议都将不胜感激!
解决方案
这是一个正则表达式,它将通过查找不同的特征来提取组和选项(组以 结尾{
,选项以 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
)
)
)
推荐阅读
- c++ - QObject::findChild 为添加到状态栏的 QLabel 返回 0
- node.js - Nodejs 请求的行为不同于 Postman 和 Curl
- botframework - 如何使用 Skype for business bot 中的电子邮件 ID 获取 Microsoft Graph 访问令牌以将事件添加到日历
- android - Arduino蓝牙通信问题
- java - 编码的逗号被忽略并被转换为数组
- c# - 简单的文件操作应用程序,新实例是帮助还是伤害?
- cypress - 如何在 Cypress IO 中更改日志文件的目的地
- javascript - JavaScript 切换类 Onclick
- java - 如何使用嵌入式 tomcat 9 创建可执行 jar?
- c - 文件太大时 fscanf 无法读取整个文件