如何用AWK解析类YAML格式文件提取子键对应值?
实现基于类YAML结构的键值提取函数
问题背景
我有一个名为data.txt的文件,内容如下:
apple: weight: 15 color: red banana: weight: 30 length: 12 grape: weight: 5 peach: weight: 25 color: orange length: 4
需要用Bash和AWK编写一个get_value函数,实现根据父键和子键提取对应值的功能,要求满足以下测试场景:
function get_value(parent_key, child_key){ ... } # Test 1 expected=15 actual=$(get_value apple weight) # 苹果有weight属性 # Test 2 expected=red actual=$(get_value apple color) # 苹果有color属性 # Test 3 expected="" actual=$(get_value apple length) # 苹果没有length属性 # Test 4 expected="" actual=$(get_value banana color) # 香蕉没有color属性
限制条件:不能使用Perl或Python,该文件并非标准YAML,仅包含两层键值结构,用冒号分隔。
我尝试过以下脚本,但无法处理子键不存在时返回空值的情况:
awk "/$key"'/ {found=1} found && /'"$child_key:"'/{print; found=0}' data.txt
解决方案:改进的AWK实现
以下是符合需求的get_value函数,通过精确匹配父键范围并处理未找到子键的场景:
get_value() { local parent_key="$1" local child_key="$2" awk -v parent="$parent_key" -v child="$child_key" ' # 精确匹配目标父键行(避免部分匹配) $0 ~ "^" parent ":" { in_parent = 1 next } # 遇到新的非缩进行(新父键),退出当前父键范围 in_parent && !/^[[:space:]]/ { in_parent = 0 } # 在父键范围内匹配目标子键 in_parent && $0 ~ "^[[:space:]]+" child ":" { # 移除键名和冒号部分,提取值 sub(/^[[:space:]]+[^:]+:[[:space:]]*/, "", $0) print $0 in_parent = 0 } ' data.txt }
核心逻辑说明
- 精确父键匹配:使用
^" parent ":"确保只匹配以目标父键开头且紧跟冒号的行,避免类似applepie:这类误匹配。 - 范围控制:通过
in_parent变量标记是否处于目标父键的子项区域,当遇到新的非缩进行时,关闭标记,停止后续查找。 - 值提取与空值处理:匹配到子键后,用
sub函数移除键名、冒号及前后空格,输出纯值;如果未找到子键,AWK不会输出任何内容,函数自然返回空字符串,符合测试要求。
测试验证
执行以下代码验证功能:
# Test 1 expected=15 actual=$(get_value apple weight) echo "Test 1: expected=$expected, actual=$actual" # Test 2 expected=red actual=$(get_value apple color) echo "Test 2: expected=$expected, actual=$actual" # Test 3 expected="" actual=$(get_value apple length) echo "Test 3: expected='$expected', actual='$actual'" # Test 4 expected="" actual=$(get_value banana color) echo "Test 4: expected='$expected', actual='$actual'"
输出结果:
Test 1: expected=15, actual=15 Test 2: expected=red, actual=red Test 3: expected='', actual='' Test 4: expected='', actual=''
内容的提问来源于stack exchange,提问作者CodingFrog
相关产品推荐
相关产品推荐

