本文介绍一种健壮、易维护的方法,将类似配置文件结构的文本(如 `host { ... }` 块)逐行解析为嵌套 php 数组,支持读取、修改与后续序列化操作。
在实际开发中,当程序受限于历史原因将结构化数据以纯文本形式(非 JSON/YAML/INI)存储时,我们需要一种可靠的方式将其“结构化还原”。你提供的配置片段具有清晰的块级语义:每个 Host { ... } 包含若干 Key = Value 形式的属性行。直接使用 strpos/substr 进行字符串匹配容易出错(如嵌套括号、空格不一致、注释干扰等),而基于按行解析 + 状态机逻辑的方法更稳定、可读性更强。
以下是一个生产就绪的解析函数:
function hostsToArray(string $filepath): array { // 读取文件并预处理:去除空行、首尾空白 $lines = array_map('trim', file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); $hosts = []; $currentHostIndex = -1; // 初始化为 -1,首次遇到 "Host {" 时置为 0 $inHostBlock = false; foreach ($lines as $line) { if ($line === 'Host {') { $currentHostIndex++; $hosts[$currentHostIndex] = []; $inHostBlock = true; continue; } if ($line === '}') { $inHostBlock = false; continue; } if ($inHostBlock && strpos($line, '=') !== false) { // 安全分割:仅按第一个 '=' 切分,避免值中含 '=' 导致错误(如 URL) $parts = explode(' = ', $line, 2); if (count($parts) === 2) { [$key, $value] = $parts; $hosts[$currentHostIndex][trim($key)] = trim($value); } } // 忽略非 Host 块内的其他行(如注释、空行已过滤,此处可扩展日志警告) } return $hosts; }
✅ 使用示例:
$hosts = hostsToArray('/etc/Program/Hosts.conf');
print_r($hosts);
// 输出:
// Array (
// [0] => Array ( [Name] => test1 [Address] => 192.168.0.1 [Port] => 8080 )
// [1] => Array ( [Name] => test2 [Address] => 192.168.0.2 [Port] => 8080 )
// )⚠️ 关键注意事项:
? 提示:若未来需高频读写,建议将此解析逻辑封装为 HostConfig 类,添加缓存、校验(如必填字段 Name, Address)、以及原子写入(file_put_contents(..., LOCK_EX))等工业级特性。