如何使用bash、sed、grep或awk从无效JSON中提取指定字段?
问题排查
你的脚本运行异常有三个核心原因:
- for循环拆分规则问题:bash的
for in循环默认按照IFS(内部字段分隔符,默认包含空格、制表符、换行符)分割输入内容,你的每条条目里有大量空格,所以会被拆成一个个小片段,而不是按行拆分。按行读取应该用while IFS= read -r结构。 - 变量赋值语法错误:你写的
component=echo $each | awk ...是错误语法,捕获命令输出需要用$()包裹,正确写法是component=$(echo $each | awk ...)。 - jq报错原因:一是该内容本身不符合JSON规范(键没有双引号、字符串值没有双引号、外层没有数组包裹),二是
$x没有用双引号包裹,被shell按空格拆分后传给jq的内容是截断的。
解决方案1:转成合法JSON后用jq解析(推荐)
用sed先补全JSON的缺失格式,就可以直接用jq处理:
# 补全JSON格式后直接输出结果 echo "[$x]" | sed -E 's/([a-zA-Z0-9]+): /"\1": /g' | sed -E 's/: ([^0-9n][^,}]*)/: "\1"/g' | jq '.[] | select(.componentId | startswith("00N") | not) | {componentName, referenceName}'
如果需要遍历处理提取到的值,可以用以下写法:
echo "[$x]" | sed -E 's/([a-zA-Z0-9]+): /"\1": /g' | sed -E 's/: ([^0-9n][^,}]*)/: "\1"/g' | jq -c '.[] | select(.componentId | startswith("00N") | not)' | while IFS= read -r entry; do component=$(echo "$entry" | jq -r '.componentName') reference=$(echo "$entry" | jq -r '.referenceName') echo "component: $component" echo "reference: $reference" done
解决方案2:直接用awk匹配提取
如果环境受限无法使用jq,直接用awk按规则拆分提取即可:
echo "$x" | awk -v RS='}, {' ' { match($0, /componentId: ([^,]+),/, id) if (id[1] !~ /^00N/) { match($0, /componentName: ([^,]+),/, comp) match($0, /referenceName: ([^,]+),/, ref) print "component: " comp[1] print "reference: " ref[1] } }'
这个方法直接用}, {作为条目分隔符,不需要处理JSON格式,更轻量。
内容的提问来源于stack exchange,提问作者Patlatus
相关产品推荐
相关产品推荐

