如何在jq中排除特定子树,修改其余节点的x键值?
如何用jq替换非
to_exclude子树中所有"x"键的值为"anything" 问题背景
给定如下JSON输入:
{ "to_exclude": { "x": "something", "aa": { "x": "something", "aaa": { "x": "something" } } }, "a": { "x": "something else", "aa": { "x": "something else", "aaa": { "x": "something else" } } }, "b": { "x": "something else", "bb": { "x": "something else", "bbb": { "x": "something else" } } }, "...": { "x": "something else", "......": { "x": "something else", ".........": { "x": "something else" } } } }
需求是:将所有不属于to_exclude子树的"x"键值替换为"anything",预期输出如下:
{ "to_exclude": { "x": "something", "aa": { "x": "something", "aaa": { "x": "something" } } }, "a": { "x": "anything", "aa": { "x": "anything", "aaa": { "x": "anything" } } }, "b": { "x": "anything", "bb": { "x": "anything", "bbb": { "x": "anything" } } }, "...": { "x": "anything", "......": { "x": "anything", ".........": { "x": "anything" } } } }
目前已经掌握相反操作(修改to_exclude子树下所有"x"键值)的简洁jq代码:
.to_exclude |= (.. |= ( if type == "object" and has("x") then .x = "anything" else . end))
该代码的输出为:
{ "to_exclude": { "x": "anything", "aa": { "x": "anything", "aaa": { "x": "anything" } } }, "a": { "x": "something else", "aa": { "x": "something else", "aaa": { "x": "something else" } } }, "b": { "x": "something else", "bb": { "x": "something else", "bbb": { "x": "something else" } } }, "...": { "x": "something else", "......": { "x": "something else", ".........": { "x": "something else" } } } }
请问如何用类似简洁的方式实现目标需求?
解决方案
可以采用「先全局替换,再恢复目标子树」的思路,代码简洁且逻辑清晰:
($in | .to_exclude) as $original_exclude | (.. |= (if type == "object" and has("x") then .x = "anything" else . end)) | .to_exclude = $original_exclude
代码解释
($in | .to_exclude) as $original_exclude:先将原始JSON中的to_exclude子树保存到变量$original_exclude中,避免后续替换操作覆盖它。(.. |= (if type == "object" and has("x") then .x = "anything" else . end)):遍历整个JSON结构,将所有包含"x"键的对象中的"x"值替换为"anything"(这一步会同时修改to_exclude里的x)。.to_exclude = $original_exclude:将之前保存的原始to_exclude子树重新赋值回去,恢复其中所有"x"的原始值。
执行这段代码后,就能得到预期的输出结果。
内容的提问来源于stack exchange,提问作者yaccob
相关产品推荐
相关产品推荐

