JQ Select by child object value with varying parent object name

JQ Select by child object value with varying parent object name

我有 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 根据 "user" 值打印 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 address:port 都是唯一的),我无法弄清楚如何构建这样的表达式。

我整天都在为这个问题苦思冥想,一直没弄明白。任何帮助将不胜感激!

"The whole line" 本身不是有效的 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"
  }
}

这是一个使用 tostreamselectforeach 的解决方案使用 "user:"bob" 和 return 枚举对象的路径 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]) }