【问题标题】:jq JSON display all values on same linejq JSON在同一行显示所有值
【发布时间】:2020-12-17 12:46:19
【问题描述】:

我确信这很简单,但我已经尝试了几个小时。

我想在 appservice 数组下显示每个对象中的两个值,并在一行中列出每个块的两个值以及相关的 IP 和名称。

我的 JSON 是这样的:

{
  "allow": [
    {
      "name": "username1",
      "scm": "true",
      "ipstart": "192.168.1.2",
      "ipend": "192.168.1.2",
      "cidr": "/32",
      "resources": [
        {
          "appservice": [
            {
              "resourcegroup": "resourcegroup1",
              "resource": "resource1"
            },
            {
              "resourcegroup": "resourcegroup2",
              "resource": "resource2"
            }
          ]
        },
        {
          "sqlserver": [
            {
              "resourcegroup": "resourcegroup3",
              "resource": "resource3"
            },
            {
              "resourcegroup": "resourcegroup4",
              "resource": "resource4"
            }
          ]
        }
      ]
    },
    {
      "name": "username2",
...
...

我想这样结束:

192.168.1.2 resourcegroup1 resource1 username1
192.168.1.2 resourcegroup2 resource2 username1

192.168.1.3 resourcegroup5 resource5 username2
192.168.1.3 resourcegroup6 resource6 username2

我试过了:

jq -r '.allow[] | "\(.ipstart) \(.resources[].appservice[]?.resourcegroup) \(.resources[].appservice[]?.resource) \(.name)"' test.json

这必须迭代太多次,因为我得到双倍的行,并且“资源组”名称与“资源”名称不匹配

192.168.1.2 resourcegroup1 resource1 username1
192.168.1.2 resourcegroup2 resource1 username1
192.168.1.2 resourcegroup1 resource2 username1
192.168.1.2 resourcegroup2 resource2 username1
192.168.1.3 resourcegroup5 resource5 username2
192.168.1.3 resourcegroup6 resource5 username2
192.168.1.3 resourcegroup5 resource6 username2
192.168.1.3 resourcegroup6 resource6 username2

我试过了:

jq -r '.allow[] | "\(.ipstart) \(.resources[].appservice[]? | .[])  \(.name)"' test.json

这给了我:

192.168.1.2 resourcegroup1  username1
192.168.1.2 resource1  username1
192.168.1.2 resourcegroup2  username1
192.168.1.2 resource2  username1
192.168.1.3 resourcegroup5  username2
192.168.1.3 resource5  username2
192.168.1.3 resourcegroup6  username2
192.168.1.3 resource6  username2

我也尝试了其他组合,但以上是最接近的。 我可以做一些 sed/awk 工作来重新解析 jq 输出,但我确信必须有一些非常简单的方法通过 jq 来避免重新解析它。

【问题讨论】:

  • 192.168.1.3s 是从哪里来的?

标签: json jq csv


【解决方案1】:

这个简单的变化不应该有你尝试的笛卡尔积问题。您的错误似乎是过早引入字符串插值。

jq -r '.allow[]
       | {ipstart,name} + .resources[].appservice[]?
       | "\(.ipstart) \(.resourcegroup) \(.resource) \(.name)"
' file.json

【讨论】:

  • 太棒了 - 毕竟它是如此简单 - 一旦你知道我的猜测就很容易:-) 非常感谢。
【解决方案2】:

可能有更短的方法,但这似乎可行:

jq -r '.allow[]
       | .ipstart as $ip | .name as $name
       | .resources[].appservice | select(.)
       | .[].name |= $name | .[].ip |= $ip
       | .[] | [.ip, .resourcegroup, .resource, .name]
       | @tsv
' file.json

【讨论】:

  • 太好了。我可能一直期望它更简单,因此我从来没有像您建议的那样进行更“复杂”的查询。我将努力通过你的例子来确保我理解它是如何工作的。非常感谢。
【解决方案3】:

如果你想要空格分隔的值(不管值是否包含空格),你可以使用join/1:

jq -r '.allow[]
   | [.ipstart] 
     + (.resources[].appservice[]?
        | [.resourcegroup, .resource]) 
     + [.name]
   | join(" ")
 ' file.json 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 2020-12-31
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    相关资源
    最近更新 更多