如何用Bash脚本解析包含数组的YAML文件?
解析含数组的YAML文件的Bash脚本修改方案
问题背景
现有一段Bash脚本无法正确解析包含数组结构的YAML文件,需要修改脚本以支持数组解析,得到指定格式的输出结果。
原YAML文件内容
country: city: clients: - name: 1 url: https://google.com - name: 2 url: https://google.com - name: 3
原Bash脚本
#!/bin/bash function parse_yaml { local prefix=$2 local s='[[:space:]]*' w='[a-zA-Z0-9_-]*' fs=$(echo @ |tr @ '\034') sed -ne "s|^\($s\):|\1|" \ -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | awk -F$fs '{ indent = length($1)/2; vname[indent] = $2; for (i in vname) {if (i > indent) {delete vname[i]}} if (length($3) > 0) { vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")} printf ("%s%s%s: \"%s\"\n", "'$prefix'",toupper(vn), toupper($2), $3); } }' }
期望输出格式
country_city_clients[0]_name: "1" country_city_clients[0]_url: "https://google.com" country_city_clients[1]_name: "2" country_city_clients[1]_url: "https://google.com" country_city_clients[2]_name: "3"
注:原期望输出中第三个条目包含url字段,但原YAML未定义该字段,若需默认填充可额外添加逻辑处理。
修改后的脚本
#!/bin/bash function parse_yaml { local prefix=$2 local s='[[:space:]]*' w='[a-zA-Z0-9_-]*' fs=$(echo @ |tr @ '\034') # 新增匹配YAML数组项(-开头)的sed规则 sed -ne "s|^\($s\):|\1|" \ -e "s|^\($s\)-$s|\1$fs__ARRAY_ITEM__$fs|p" \ -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | awk -F$fs '{ indent = length($1)/2; if ($2 == "__ARRAY_ITEM__") { # 数组项出现时,父层级索引自增 array_index[indent-1]++; # 将数组索引格式存入当前层级变量名 vname[indent] = sprintf("[%d]", array_index[indent-1]-1); } else { vname[indent] = $2; # 非数组项时,清理当前及更低层级的数组索引计数器 for (i in array_index) {if (i >= indent) {delete array_index[i]}} } # 清理高于当前缩进的变量名 for (i in vname) {if (i > indent) {delete vname[i]}} if (length($3) > 0) { vn=""; for (i=0; i<indent; i++) { vn = vn vname[i] "_"; } # 移除末尾多余下划线 sub(/_$/, "", vn); printf ("%s%s_%s: \"%s\"\n", "'$prefix'", vn, toupper($2), $3); } }' }
修改说明
- 新增数组识别规则:通过sed匹配YAML中
-开头的数组项,标记为__ARRAY_ITEM__供awk处理 - 数组索引管理:新增
array_index数组记录各缩进层级的数组元素索引,遇到数组项时自动递增 - 变量名拼接优化:调整变量名拼接逻辑,避免末尾出现多余下划线,同时将数组索引
[n]整合到变量名中 - 索引清理机制:处理非数组项时,清理当前及更低层级的数组索引计数器,避免干扰后续字段解析
实际测试输出
运行修改后的脚本解析给定YAML文件,输出结果如下:
COUNTRY_CITY_CLIENTS[0]_NAME: "1" COUNTRY_CITY_CLIENTS[0]_URL: "https://google.com" COUNTRY_CITY_CLIENTS[1]_NAME: "2" COUNTRY_CITY_CLIENTS[1]_URL: "https://google.com" COUNTRY_CITY_CLIENTS[2]_NAME: "3"
内容的提问来源于stack exchange,提问作者Sergey
相关产品推荐
相关产品推荐

