PHP 如何按方括号中的分组名将文件内容转换为多维数组?
可以直接使用 parse_ini_file()。示例中的 [People]、[Person_1] 是 INI 分组,后面的 key=value 是配置项。将第二个参数设为 true,就可以按分组生成二维关联数组,无需自己用 explode() 拆分。
使用 parse_ini_file() 解析
假设文件内容符合 INI 语法,要把 Name=Joe 解析为 'Name' => 'Joe',可以这样写:
<?php
$filename = 'data.txt';
$finalarray = parse_ini_file($filename, true, INI_SCANNER_RAW);
if ($finalarray === false) {
throw new RuntimeException('无法读取或解析文件:' . $filename);
}
print_r($finalarray);
参数分别表示:
$filename:待解析的文件路径。true:保留分组,将每个分组解析为一个子数组。INI_SCANNER_RAW:使用原始扫描模式,避免对配置值进行 INI 特殊值解释,示例中的数字也会保留为字符串。
示例数据对应的数组结构如下:
[
'People' => [
'people_count' => '5',
'male_count' => '3',
'female_count' => '2',
],
'Person_1' => [
'Name' => 'Joe',
'Sex' => 'male',
'Age' => '55',
'Other' => 'X',
],
'Person_2' => [
'Name' => 'Jill',
'Sex' => 'female',
'Age' => '25',
],
'Person_3' => [
'Name' => 'Bob',
'Age' => '15',
],
]
每个分组可以有不同数量的配置项,无需预先定义字段。读取某个人的姓名时,可以直接使用:
echo $finalarray['Person_1']['Name']; // Joe
原来的循环为什么没有正确分组?
原代码识别了方括号,却没有记录当前正在处理的分组。
$data = array($matches);
array_push($finalarray, $data);
$matches 本身已经是数组,再用 array($matches) 包装会增加一层嵌套。随后调用:
array_push($finalarray, $val);
又把普通数据行追加到了最外层数组,导致标题和数据无法组成对应的父子结构。另外,$data 是数组,不能用作 $finalarray[$data] 的数组键。
手动解析时,需要保存当前分组名,再将数据写入对应位置。例如,下面的循环会保留每条原始数据行:
$finalarray = [];
$section = null;
foreach ($array as $val) {
$val = trim($val);
if ($val === '') {
continue;
}
if (preg_match('/^\[([^\]]+)\]$/', $val, $matches)) {
$section = $matches[1];
$finalarray[$section] = [];
continue;
}
if ($section === null) {
throw new RuntimeException('数据行之前缺少分组标题');
}
$finalarray[$section][] = $val;
}
这个版本得到的是字符串列表,例如:
[
'Person_1' => [
'Name=Joe',
'Sex=male',
'Age=55',
'Other=X',
],
]
如果需要关联数组,可以将循环末尾的追加语句替换为:
$pair = explode('=', $val, 2);
if (count($pair) !== 2) {
throw new RuntimeException('无效的数据行:' . $val);
}
$key = trim($pair[0]);
$value = trim($pair[1]);
$finalarray[$section][$key] = $value;
explode('=', $val, 2) 只按第一个等号拆分,因此值中即使包含 =,也能保留下来。这种手动处理适用于自行约定的简单文本格式,不具备完整的 INI 引号、注释等解析规则。
使用时需要注意什么?
对于题目给出的格式,优先使用 parse_ini_file()。如果实际文件包含不符合 INI 语法的自定义内容,可以按明确的文件规则自行解析。
同一分组内若出现重复键,关联数组无法保留这些键的所有独立记录;上面转换为关联数组的手动版本也会用后一个值覆盖前一个值。需要保留重复数据时,应使用列表结构。
原代码在 print_r($finalarray); 后还有一个多余的 }。如果所贴代码就是完整脚本,需要删除它。示例中的 people_count=5 也只会作为配置值读取,解析过程不会检查它是否与实际的 Person_X 分组数量一致。
备注:内容仅供参考。
