You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在jq中实现对象减法操作?

用jq实现递归反向移除(类似反向meld操作)

我们知道可以用jq的*运算符递归合并两个对象,比如执行:

jq '.[0] * .[1]' -s a.json b.json

但这个方法无法合并数组,不过已有对应的解决思路。现在需要实现相反的操作:从a.json中移除所有在b.json里存在的内容(已知b.json的所有内容都存在于a.json中)。

示例数据

a.json

{
  "background": {
    "service_worker": "js/background.js",
    "type": "module"
  },
  "manifest_version": 3,
  "permissions": [
    "storage",
    "unlimitedStorage"
  ]
}

b.json

{
  "background": {
    "type": "module"
  },
  "permissions": [
    "unlimitedStorage"
  ]
}

预期结果

{
  "background": {
    "service_worker": "js/background.js"
  },
  "manifest_version": 3,
  "permissions": [
    "storage"
  ]
}

通用解决方案

可以定义一个递归的jq函数remove来实现这个逻辑,兼容嵌套对象和数组处理:

def remove($b):
  if type == $b.type then
    if type == "object" then
      reduce keys[] as $k ({};
        if ($b | has($k)) then
          ($[$k] | remove($b[$k])) as $val
          | if $val | (type == "object" and length > 0) or (type == "array" and length > 0) or (type | IN("string","number","boolean","null")) then
            . + {($k): $val}
          else
            .
          end
        else
          . + {($k): $[$k]}
        end
      )
    elif type == "array" then
      [.[] as $item | if $b | index($item) then empty else $item end]
    else
      if . != $b then . else empty end
    end
  else
    .
  end;

使用方法

执行以下命令,将b.json作为参数传入处理a.json:

jq --argfile b b.json 'remove($b)' a.json

逻辑说明

  • 对象处理:遍历原对象的每个键,若对比对象(b)中存在该键,则递归处理对应的值;只有当处理后的值为非空对象、非空数组,或是与b中值不同的基本类型时,才保留该键。
  • 数组处理:过滤掉原数组中所有在对比数组(b)里存在的元素。
  • 基本类型:若原值与b中的值相同则移除,否则保留。

内容的提问来源于stack exchange,提问作者kaya51

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 08:02:34