定位JSON内'id'键后重命名同作用域'answer'键为'answer_id'的实现方案
嵌套JSON指定作用域字段重命名实现方案
现有awk脚本失效的核心原因
你写的逐行awk脚本存在三个无法绕开的硬伤,根本匹配不到预期的修改目标:
- awk默认按空白分割字段,遇到带引号、冒号的JSON键值对(比如
"id": "77"),会把引号、冒号拆成独立的孤立字段,根本无法精准识别“键名等于id”的语义; - 脚本里的作用域标记
r是全局变量,没有绑定到id节点所在的对象层级,一旦匹配到id就会永久触发修改逻辑,完全区分不开同作用域和跨作用域的answer字段,自然会出现匹配偏差; - 就算你在awk里靠计数大括号的方式估算嵌套层级,遇到字符串值里包含大括号的场景,马上就会出现层级计算错误,根本没法精准识别JSON对象的边界。
正确实现逻辑
处理带嵌套层级的JSON语义,不能靠纯文本正则匹配,必须用结构化JSON解析器实现,核心逻辑完全对应需求:
- 递归遍历整棵JSON对象树,定位所有包含
id键的对象节点; - 对每个匹配到id的节点,检索它所在作用域及所有子层级内的字段,将键名为
answer的字段统一重命名为answer_id; - 所有不在id节点作用域覆盖范围内的
answer字段,完全保留原键名不做修改。
可直接运行的处理命令
用jq(轻量结构化JSON解析工具)实现上述逻辑的脚本如下,处理结果和给定的期望输出完全一致:
def rename_in_scope: if has("id") then with_entries( .key as $k | if $k == "answer" then .key = "answer_id" else if (.value | type) == "object" then .value |= rename_in_scope else . end end ) else with_entries( if (.value | type) == "object" then .value |= rename_in_scope else . end ) end; .quiz |= rename_in_scope
实际执行时,直接在终端运行:jq '上述脚本内容' example.json > example2.json
方案适配效果
对应提供的测试JSON结构:
sport对象本身包含id键,所以它下属嵌套的q1节点内的answer字段会被重命名为answer_id;maths对象本身不包含id键,所以它下属嵌套的q1节点内的answer字段会保留原键名,完全符合预期。
注:不要硬靠awk/正则处理这类嵌套JSON语义,一旦遇到格式缩进变化、特殊字符转义、嵌套层级调整的情况,纯文本匹配脚本会直接失效,维护成本极高,结构化解析器是这类场景的可靠方案。
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

