【问题标题】:jq - subtracting one array from another using a single commandjq - 使用单个命令从另一个数组中减去一个数组
【发布时间】:2020-09-13 19:36:53
【问题描述】:

我对 jq 进行了三个操作以获得正确的结果。我怎样才能在一个命令中做到这一点? 这是源 JSON 文件的片段

[
    {
        "Header": {
            "Tenant": "tenant-1",
            "Rcode": 200
        },
        "Body": {
            "values": [
                {
                    "id": "0b0b-0c0c",
                    "name": "NumberOfSearchResults"
                },
                {
                    "id": "aaaa0001-0a0a",
                    "name": "LoadTest"
                }
            ]
        }
    },
    {
        "Header": {
            "Tenant": "tenant-2",
            "Rcode": 200
        },
        "Body": {
            "values": []
        }
    },
    {
        "Header": {
            "Tenant": "tenant-3",
            "Rcode": 200
        },
        "Body": {
            "values": [
                {
                    "id": "cccca0003-0b0b",
                    "name": "LoadTest"
                }
            ]
        }
    },
    {
        "Header": {
            "Tenant": "tenant-4",
            "Rcode": 200
        },
        "Body": {
            "values": [
                {
                    "id": "0f0g-0e0a",
                    "name": "NumberOfSearchResults"
                }
            ]
        }
    }
]

我应用了两个过滤器并创建了两个中间 JSON 文件。首先,我创建所有租户的列表

jq -r '[.[].Header.Tenant]' source.json >all-tenants.json

然后我选择创建一个包含所有租户的数组,这些租户在 Body.values[] 数组中没有特定键:

jq -r '[.[] | select (all(.Body.values[]; .name !="LoadTest")  )  ] | [.[].Header.Tenant]' source.json >filter1.json

结果 - all-tenants.json

["tenant-1",
"tenant-2",
"tenant-3",
"tenant-4"
]

filter1.json

["tenant-2",
"tenant-4"
]

然后我从 all-tenants.json 中构造 filter1.json 以获得差异:

jq  -r -n --argfile filter filter1.json --argfile alltenants all-tenants.json '$alltenants - $filter|.[]'

结果:

tenant-1
tenant-3

租户名称 - “租户”键的值是唯一的,并且每个值在 source.json 文件中只出现一次。

澄清一下 - 我知道我可以有一个选择条件,它会给我与减去两个数组相同的结果。

我想了解的 - 如何在不涉及中间文件的单个命令中直接将这两个数组分配和使用到 vars 中?

谢谢

【问题讨论】:

    标签: arrays json sorting split jq


    【解决方案1】:

    使用过滤器填充新对象的值并使用键来引用数组。

    jq -r '{
             "all-tenants": [.[].Header.Tenant],
             "filter1": [.[]|select (all(.Body.values[]; .name !="LoadTest"))]|[.[].Header.Tenant]
           } | .["all-tenants"] - .filter1 | .[]'
    

    注意:.["all-tenants"] 是该键中的特殊字符“-”所必需的。请参阅手册中Object Identifier-Index 下的条目。

    【讨论】:

    • 这是我第一次看到select(all(...; ...));真正的成语。
    • 谢谢,所以本质上,您的解决方案是创建一个包含两个数组的新对象,然后从另一个数组中减去一个,对吗?如果是这样,创建其他对象是否是不必要的操作?
    • 没错。您需要参考您的两个数组。将它们分配给 $-variables 是一种方法:您使用分配的 $-variable 引用数组。使用对象的键值结构是另一回事:您使用分配的键来引用数组。您需要为第二个解决方案创建一个对象,并且您需要为第一个解决方案创建变量。
    【解决方案2】:

    如何在不涉及中间文件的单个命令中直接将这两个数组分配和使用到 var 中?

    只需将中间数组存储为 jq "$-variables":

    [.[].Header.Tenant] as $x
    | ([.[] | select (all(.Body.values[]; .name !="LoadTest")  )  ] | [.[].Header.Tenant]) as $y
    | $x - $y
    

    如果您想逐项列出 $x - $y 的内容,只需将最终的 .[] 添加到管道即可。

    【讨论】:

      猜你喜欢
      • 2013-02-21
      • 1970-01-01
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-27
      相关资源
      最近更新 更多