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

jq入门者求助:如何按匹配规则将JSON数组跨文件添加

用jq实现跨JSON文件的数组匹配追加

嘿,作为jq初学者能想到用专门的JSON工具而不是sed/grep,这思路太赞了!完全可以用jq优雅解决你的需求,我一步步给你拆解清楚。

先明确场景(假设的JSON结构)

首先我先假设两个文件的结构,这样更容易理解命令逻辑——如果你的实际结构有差异,调整对应的字段名就行:

file_1.json 示例

[
  {
    "id": "item1",
    "physical_endpoint": "https://hostname/api/v1",
    "url": []
  },
  {
    "id": "item2",
    "physical_endpoint": "http://hostname/service",
    "url": []
  },
  {
    "id": "item3",
    "physical_endpoint": "https://otherhost/test",
    "url": []
  }
]

file_2.json 示例

[
  {
    "endpoint": "https://hostname/api/v1",
    "url": ["https://hostname/api/v1/foo", "https://hostname/api/v1/bar"]
  },
  {
    "endpoint": "http://hostname/service",
    "url": ["http://hostname/service/baz"]
  },
  {
    "endpoint": "https://otherhost/test",
    "url": []
  }
]

核心命令实现

我们的思路是:先把file_2的数据转成一个「endpoint -> url数组」的映射表(方便快速查找),然后遍历file_1的条目,筛选出符合前缀规则的条目,再把匹配到的url数组追加进去。

直接用这条命令:

jq --argfile file2 file_2.json '
  # 把file2转成以endpoint为键的映射表,方便快速查找
  ($file2 | INDEX(.endpoint)) as $endpoint_map
  # 遍历file1的每个条目
  | map(
      # 筛选出以http[s]://hostname/开头的physical_endpoint
      if .physical_endpoint | test("^https?://hostname/") then
        # 追加匹配到的url数组,// [] 确保没匹配到的时候加空数组,避免null
        .url += $endpoint_map[.physical_endpoint].url // []
      else
        # 不符合规则的条目保持原样
        .
      end
    )
' file_1.json

命令拆解解释

  • --argfile file2 file_2.json:把file_2.json的内容读入jq变量$file2,方便后续操作
  • ($file2 | INDEX(.endpoint)) as $endpoint_map:用jq内置的INDEX函数,把file2的数组转成一个对象,键是每个条目的endpoint值,值是整个条目——这样查找的时候直接用键值对,效率比遍历高很多
  • map(...):遍历file1的每个数组元素,逐个处理
  • test("^https?://hostname/"):用正则表达式匹配前缀,https?表示http或https,^确保是字符串开头
  • .url += ...:把找到的url数组追加到原有的url数组后面
  • // []:jq的「空值合并」操作符,如果找不到匹配的endpoint,就用空数组代替,避免出现null破坏JSON结构

保存结果

如果想把修改后的结果保存到新文件,直接重定向输出即可:

jq --argfile file2 file_2.json '...' file_1.json > updated_file_1.json

小调整:如果是模糊匹配?

如果你的「匹配项」不是完全相等,而是file2的endpoint包含file1的physical_endpoint,或者其他规则,只需要修改if条件里的判断逻辑就行。比如要匹配file2的endpoint以file1的physical_endpoint开头:

jq --argfile file2 file_2.json '
  ($file2 | INDEX(.endpoint)) as $endpoint_map
  | map(
      if .physical_endpoint | test("^https?://hostname/") then
        .url += ($file2[] | select(.endpoint | startswith(.physical_endpoint)) | .url) // []
      else
        .
      end
    )
' file_1.json

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:48:38