使用jq进行JSON重映射

3

我有以下json:

[
  {
    "ip": [
      "8.8.4.4/32",
      "212.40.11.20/32"
    ],
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": [
      "212.40.11.30/32"
    ],
    "port": 3389,
    "proto": "tcp"
  }
]

我想使用 jqip 数组中的 IP 地址分离出来,像这样:

[
  {
    "ip": "8.8.4.4/32",
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": "212.40.11.20/32",
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": "212.40.11.30/32",
    "port": 3389,
    "proto": "tcp"
  }
]

我正在使用 jq 1.5Ubuntu 15.04 上,同时使用 bash 4.3.42(1)
编辑:
这是我从 AWS 中生成此列表的方式:
aws ec2 describe-security-groups --group-id sg-2cf5e31 --query 'SecurityGroups[].IpPermissions[].{port:ToPort,proto:IpProtocol,ip:IpRanges[].CidrIp[]}' | jq '.[]' 下一步是添加一个自定义字段。
感谢您的帮助。
3个回答

9
一个比@peak和@hek2mgl都更短、更简单的替代方案,但它仍然基于相同的概念运作:
jq 'map(.ip = .ip[])'

哇!简洁而清晰! - hek2mgl
运行得非常好,而且非常优雅,谢谢! - Yaron
顺便问一下,你能想到一种不使用 jq 的方法,只用 aws 工具来完成它吗? - Yaron
目前不行,但可能有人可以!我会为此创建一个单独的问题。AWS内部的--query参数采用JMESPath命令,这些命令与jq命令非常相似。 - user3899165

4
$ jq 'map(  (.ip[] | { "ip": .}) + del(.ip) )' input.json
[
  {
    "ip": "8.8.4.4/32",
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": "212.40.11.20/32",
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": "212.40.11.30/32",
    "port": 3389,
    "proto": "tcp"
  }
]

同样地,可以写成map( . + {ip:.ip[]} )

这意味着(这也是jq强大之处之一),如果STREAMn是长度为n的流,则假设(value + x)对于流中的每个项目都有效,那么value + STREAMn将产生长度为n的流。

实际上,假设可以逐对添加项,则STREAMn + STREAMm会产生长度为m * n的“笛卡尔积流”。


2

除了Peak的好方法,您还可以使用以下表达式:

jq '[.[]|{ip:.ip[],port,proto}]' aws.json

它很好地展示了jq如何“压扁”ip数组。
输出:
[
  {
    "ip": "8.8.4.4/32",
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": "212.40.11.20/32",
    "port": 25,
    "proto": "tcp"
  },
  {
    "ip": "212.40.11.30/32",
    "port": 3389,
    "proto": "tcp"
  }
]

非常感谢,你也很棒! - Yaron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接