JQ按子对象值选择,具有不同的父对象名称

时间:2016-02-19 21:53:57

标签: json jq

我有json:

{
  "interfaces": {
    "UDPInterface": [
      {
        "connectTo": {
          "1.2.3.4:25925": {
            "user": "bob",
            "password": "aaaaaaaa",
            "publicKey": "foirncnqwpnqwopnqrrvn308g9h4b.k"
          },
          "4.3.2.1:24970": {
            "user": "sam",
            "password": "bbbbbbbb",
            "publicKey": "v09ervn4uvr78cweyclfirnfuq3c9pwper.k"
          },
          "1.3.4.2:41872": {
            "user": "betty",
            "password": "cccccccccc",
            "publicKey": "crnn497hg3j34f34uvrnfwmnriuhqrmoweje.k"
          }
        },
        "bind": "0.0.0.0:64660"
      },
      {
        "connectTo": {},
        "bind": "[::]:54887"
      }
    ]
  }
}

并希望能够使用jq打印基于"用户"的IP地址行的内容。值。我可以接近这个:

jq '.interfaces.UDPInterface[0].connectTo."1.2.3.4:25925" | select(.user | contains("bob"))'

但是,这只给出了1.2.3.4:25925对象的值:

{"user" : "bob", "password" : "aaaaaaaa", "publicKey" : "foirncnqwpnqwopnqrrvn308g9h4b.k"},

当我需要的是整条线:

"1.2.3.4:25925" : {"user" : "bob", "password" : "aaaaaaaa", "publicKey" : "foirncnqwpnqwopnqrrvn308g9h4b.k"},

但是,我无法弄清楚如何在不知道父对象名称的情况下构建这样的表达式(每个IP地址:端口都是唯一的)。

我整天都在反对这一切,而且我们已经能够解决这个问题了。任何帮助将非常感谢!

2 个答案:

答案 0 :(得分:0)

“整行”本身不是有效的JSON对象。您可以获得包含与谓词匹配的所有元素的对象;这将是一种方式:

jq '.interfaces.UDPInterface[0].connectTo | with_entries(select(.value.user | contains("bob")))'

您输入的输出将是:

{
  "1.2.3.4:25925": {
    "user": "bob",
    "password": "aaaaaaaa",
    "publicKey": "foirncnqwpnqwopnqrrvn308g9h4b.k"
  }
}

答案 1 :(得分:0)

这是一个解决方案,它使用 tostream 选择 foreach 来枚举带有“user:”bob“的对象的路径并返回那些使用 getpath

获取所需格式的对象
foreach (   tostream
          | select(length == 2 and .[0][-1] == "user" and .[1] == "bob")
          | .[0]
        ) as $p (
     .
   ; .
   ; { ($p[-2]): getpath($p[:-1]) }
)

编辑:我现在意识到foreach E as $X (.; .; R)形式的过滤器几乎总是被重写为E as $X | R所以上面的内容实际上就是

  ( tostream | select(length == 2 and .[0][-1] == "user" and .[1] == "bob") | .[0] ) as $p
| { ($p[-2]): getpath($p[:-1]) }