简体   繁体   English

jq - 使用单个命令从另一个数组中减去一个数组

[英]jq - subtracting one array from another using a single command

I have three operations with jq to get the right result.我对 jq 进行了三个操作以获得正确的结果。 How can I do it within one command?我怎样才能在一个命令中做到这一点? Here is a fragment from the source JSON file这是源 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"
                }
            ]
        }
    }
]

I apply two filters and create two intermediate JSON files.我应用了两个过滤器并创建了两个中间 JSON 文件。 First I create the list of all tenants首先我创建所有租户的列表

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

And then I select to create an array of all tenants not having a particular key present in the Body.values[] array:然后我选择创建一个包含Body.values[]数组中没有特定键的所有租户的数组:

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

Results - all-tenants.json结果 - all-tenants.json

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

filter1.json过滤器1.json

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

And then I substruct filter1.json from all-tenants.json to get the difference:然后我从 all-tenants.json 子结构 filter1.json 得到差异:

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

Result:结果:

tenant-1
tenant-3

Tenant names - values for the "Tenant" key are unique and each of them occurs only once in the source.json file.租户名称 - “租户”键的值是唯一的,并且每个值在 source.json 文件中只出现一次。

Just to clarify - I understand that I can have a select condition(s) that would give me the same resut as subtracting two arrays.只是为了澄清 - 我知道我可以有一个选择条件,它会给我与减去两个数组相同的结果。

What I want to understand - how can I assign and use these two arrays into vars directly in a single command not involving the intermediate files?我想了解什么 - 如何在不涉及中间文件的单个命令中直接将这两个数组分配和使用到 vars 中?

Thanks谢谢

Use your filters to fill in the values of a new object and use the keys to refer to the arrays.使用过滤器填充新对象的值并使用键来引用数组。

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

Note: .["all-tenants"] is required by the special character "-" in that key.注意:该键中的特殊字符“-”需要 .["all-tenants"] 。 See the entry under Object Identifier-Index in the manual.请参阅手册中对象标识符-索引下的条目。

how can I assign and use these two arrays into vars directly in a single command not involving the intermediate files?如何在不涉及中间文件的单个命令中直接将这两个数组分配和使用到 vars 中?

Simply store the intermediate arrays as jq "$-variables":只需将中间数组存储为 jq "$-variables":

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

If you want to itemize the contents of $x - $y, then simply add a final .[] to the pipeline.如果您想逐项列出 $x - $y 的内容,只需在管道中添加一个最终的.[]即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM