如何用Bash从PHP配置文件提取任意深度的嵌套配置值
需求:纯Bash实现PHP配置文件任意深度键值提取
问题背景
我有一个大型PHP配置文件,格式示例如下:
<some stuff before our example> 'Realtime' => [ 'foo' => 'bar', 'enabled' => true, 'lorem' => 'ipsum' ], <some stuff after our example>
需要用Bash提取指定嵌套键的值,且不能依赖PHP实现。
现有尝试及问题
我曾尝试用以下命令提取'Realtime'下的内容:
echo $(tr '\n' ' ' < myconfig.php | sed '$s/ $/\n/') | grep -o -P '(?<=Realtime).*(?=\])'
但该命令会匹配'Realtime'到最后一个]之间的所有内容,而我需要匹配到第一个闭合的]。
目前我有一套PHP结合Shell的实现逻辑,能够处理任意深度的嵌套键(比如传入Realtime.enabled),但它会将整个配置文件加载到内存中处理,我希望完全用Bash实现,摆脱对PHP的依赖:
public function getConfig($name) { $path = Paths::CONFIG_FILE; if (!$this->config) { $this->config = Command_ShellFactory::makeForServer('zl', "cat {$path}")->execute(true, true); } $splitName = explode('.', $name); $lastPosition = 0; $tempConfig = $this->config; foreach ($splitName as $currentName) { if (($position = strpos($tempConfig, $currentName)) === false) { throw new RuntimeException('Setting was not found'); } $tempConfig = substr($tempConfig, $position); } return trim(explode("=>", explode("\n", $tempConfig)[0])[1], ", \n\r\t\v\x00"); }
补充说明:嵌套深度支持
配置文件支持任意深度的嵌套结构,示例如下:
[ /*...*/ 'a' => 'b', // 深度1 'c' => [ 'a' => 'd' // 深度2 ], 'e' => [ 'f' => [ 'g' =>'h' // 深度3 ] ] /*...*/ ]
测试场景及当前命令局限
我创建了测试文件foo.sh:
[ 'Realtime' => [ 'enabled' => [ 'd' => [ 'e' => 'f' ], ], 'a' => [ 'b' => 'c' ], ] 'g' => [ 'h' => 'i' ], 'Unrealtime' => 'abc' ]
有效场景
- 一维键提取(
Unrealtime):
sed -Ez ":a;s/.*Unrealtime' => +([^,]*).*/\1\n/" foo.sh | head -1
结果:
'abc'
- 二维键提取(
g.h):
sed -Ez ":a;s/.*g[^]]*h' => +([^,]*).*/\1\n/" foo.sh | head -1
结果:
'i'
失效场景
三维及以上嵌套键的提取命令仅当目标子项是父项的第一个子项时有效:
比如提取Realtime.a.b的命令:
sed -Ez ":a;s/.*Realtime*[^]]*a[^]]*b' => +([^,]*).*/\1\n/" foo.sh | head -1
只有当'a' => [...]是Realtime的第一个子项时才能得到正确结果,实际场景中子项顺序不固定,需要不依赖子项顺序的通用解决方案。
同样,四维键Realtime.enabled.d.e的提取命令也存在相同问题:
sed -Ez ":a;s/.*Realtime[^]]*enabled[^]]*d[^]]*e' => +([^,]*).*/\1\n/" foo.sh | head -1
内容的提问来源于stack exchange,提问作者Lajos Arpad
相关产品推荐
相关产品推荐

