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

如何使用jq基于多层过滤精准更新JSON中的指定DNS记录值

如何使用jq基于多层过滤精准更新JSON中的指定DNS记录值

我完全懂你现在的困扰——想用jq精准定位到某一个DNS区域下的特定A记录,只更新它的records值,但之前试的命令要么把所有相关记录都改了,要么误改了其他区域的条目,完全达不到预期效果。别慌,我们来一步步解决这个问题。

首先先明确你的原始JSON数据(方便大家对照):

[
  {
    "dns_zone_name": "zone1",
    "a_records": [
      {
        "name": "record1",
        "records": [
          "zone1_record1_item1"
        ]
      },
      {
        "name": "record2",
        "records": [
          "zone1_record2_item1"
        ]
      }
    ]
  },
  {
    "dns_zone_name": "zone2",
    "a_records": [
      {
        "name": "record1",
        "records": [
          "zone2_record1_item1"
        ]
      },
      {
        "name": "record2",
        "records": [
          "zone2_record2_item1"
        ]
      }
    ]
  }
]

先分析你之前命令的问题

  1. 第一个命令里的select(.dns_zone_name="zone1" and .a_records[].name=="record1")有两个核心问题:

    • 用了=而不是==做比较,=是赋值操作,这会先把所有对象的dns_zone_name改成zone1,完全偏离了过滤的初衷;
    • .a_records[]会展开数组,导致匹配到zone1后,所有a_records里的条目都会被选中修改,所以才会出现所有记录都被更新的情况。
  2. 第二个命令.[].a_records |= map (select(.name=="record1").records |= ["NewRecord"])会遍历所有DNS区域,修改每个区域里名为record1的A记录,所以zone2的record1也被误改了,不符合你只修改zone1/record1的需求。

正确的jq命令写法

要实现精准定位,我们需要分层过滤:先找到目标DNS区域,再在该区域内找到目标A记录,最后更新它的records值。推荐的命令如下:

map(
  if .dns_zone_name == "zone1" then
    .a_records |= map(
      if .name == "record1" then .records = ["New"] else . end
    )
  else . end
)

命令逻辑解释

  • 外层的map遍历数组中的每一个DNS区域对象;
  • 先判断当前对象的dns_zone_name是否为zone1,如果不是,直接保持原对象不变;
  • 如果是zone1,则对它的a_records数组做内层map遍历:
    • 对每个A记录对象,判断name是否为record1,是的话就把records赋值为["New"],否则保持原记录不变;
  • 这样就只会精准修改zone1下record1的records值,其他所有条目都不受影响。

执行后的预期结果

[
  {
    "dns_zone_name": "zone1",
    "a_records": [
      {
        "name": "record1",
        "records": [
          "New"
        ]
      },
      {
        "name": "record2",
        "records": [
          "zone1_record2_item1"
        ]
      }
    ]
  },
  {
    "dns_zone_name": "zone2",
    "a_records": [
      {
        "name": "record1",
        "records": [
          "zone2_record1_item1"
        ]
      },
      {
        "name": "record2",
        "records": [
          "zone2_record2_item1"
        ]
      }
    ]
  }
]

额外小提示

如果你需要把zone1和record1做成可替换的变量(方便批量处理),可以用jq的--arg参数,比如:

jq --arg zone "zone1" --arg record "record1" '
map(
  if .dns_zone_name == $zone then
    .a_records |= map(
      if .name == $record then .records = ["New"] else . end
    )
  else . end
)' your-dns-file.json

这样就不用每次修改命令里的字符串,直接通过参数传递目标区域和记录名即可。

备注:内容来源于stack exchange,提问作者jleg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 07:55:28