Json 使用jq的Ansible输出提取包版本

Json 使用jq的Ansible输出提取包版本,json,ansible,jq,Json,Ansible,Jq,下面是ansible的json输出,我想使用jq解析这个文件。我想匹配软件包名称GeoIP和打印版本号 如何使用jq获取与包名匹配的版本号?看起来像这样 "GeoIP","1.5.0" 示例ansible输出 { "ansible_facts.packages": { "GConf2": [ { "arch": "x86_64", "epoch": null,

下面是ansible的json输出,我想使用
jq
解析这个文件。我想匹配软件包名称
GeoIP
和打印版本号

如何使用
jq
获取与包名匹配的版本号?看起来像这样

"GeoIP","1.5.0"
示例ansible输出

{
    "ansible_facts.packages": {
        "GConf2": [
            {
                "arch": "x86_64",
                "epoch": null,
                "name": "GConf2",
                "release": "8.el7",
                "source": "rpm",
                "version": "3.2.6"
            }
        ],
        "GeoIP": [
            {
                "arch": "x86_64",
                "epoch": null,
                "name": "GeoIP",
                "release": "14.el7",
                "source": "rpm",
                "version": "1.5.0"
            }
        ],
        "ImageMagick": [
            {
                "arch": "x86_64",
                "epoch": null,
                "name": "ImageMagick",
                "release": "18.el7",
                "source": "rpm",
                "version": "6.7.8.9"
            }
        ],
    }
}

我假设您希望在
ansible\u facts.packages
中的所有键值属性上获得一个循环,因此建议使用bash循环对其进行迭代。另外,您提供的json的示例内容不可编译,我从末尾删除了逗号3行

您需要一个jq来获取
ansible\u facts.packages
的所有密钥,然后在每次迭代中获取给定密钥(package)的版本

要获取所有密钥,请执行以下操作:

[http_offline@greenhat-30 tmp]$ cat file.json | jq '."ansible_facts.packages" | keys[]'
"GConf2"
"GeoIP"
"ImageMagick"
[http_offline@greenhat-30 tmp]$ 
循环:

样本运行:

[http_offline@greenhat-30 tmp]$ for package in `cat file.json | jq '."ansible_facts.packages" | keys[]'`
> do
> VERSION=`cat file.json | jq ".\"ansible_facts.packages\".$package[0].version"`
> echo "$package,$VERSION"
> done
"GConf2","3.2.6"
"GeoIP","1.5.0"
"ImageMagick","6.7.8.9"
[http_offline@greenhat-30 tmp]$ 
希望能有帮助

Q:“如何使用jq获取与包名匹配的版本号?”

A:试试下面的脚本

$ cat print-version.sh
#!/bin/sh
cat output.json | jq ".ansible_facts.packages.$1 | .[].version"
比如说

$ print-version.sh GeoIP
"1.5.0"

脚本的改进版本


引用注释:
“使用shell的字符串插值(如此处所做)是有风险的,通常被视为“反模式”。-peak“

下面改进的脚本完成了这项工作

$ cat print-version.sh
#!/bin/sh
cat output.json | jq ".ansible_facts.packages.$1[].version"

output.json

{
    "ansible_facts": {
        "packages": {
            "GConf2": [
                {
                    "arch": "x86_64",
                    "epoch": null,
                    "name": "GConf2",
                    "release": "8.el7",
                    "source": "rpm",
                    "version": "3.2.6"
                }
            ],
            "GeoIP": [
                {
                    "arch": "x86_64",
                    "epoch": null,
                    "name": "GeoIP",
                    "release": "14.el7",
                    "source": "rpm",
                    "version": "1.5.0"
                }
            ],
            "ImageMagick": [
                {
                    "arch": "x86_64",
                    "epoch": null,
                    "name": "ImageMagick",
                    "release": "18.el7",
                    "source": "rpm",
                    "version": "6.7.8.9"
                }
            ]
        }
    }
}

首先,删除从第三行到最后一行的逗号,使源json有效

完成后,我们可以从最后开始工作。可以使用jq的@csv格式生成所需的输出。这反过来又要求输出位于数组中。(请参阅标题为“格式化字符串和转义”的部分),因此我们需要使数据看起来像这样

jq -r '["GeoIP","1.5.0"] | @csv'
一种方法是将每个项放在自己的数组中,并将数组添加到一起。(见标题为“添加”。)

由于
map(x)
被定义为
[.]|x]
,因此您可以这样说

jq -r '["GeoIP"] + map(.GeoIP[].version) | @csv'
您可以使用一个变量来指定所需的包名称,如下所示

jq -r --arg "package" "GeoIP" '[$package] + map(.[$package][].version) | @csv'
jq -r '[ "GeoIP", .[].GeoIP[].version ] | @csv'
更新

我最初的解决方案有不必要的步骤。阵列可以这样制作

jq -r --arg "package" "GeoIP" '[$package] + map(.[$package][].version) | @csv'
jq -r '[ "GeoIP", .[].GeoIP[].version ] | @csv'
或者,使用变量

jq -r --arg "package" "GeoIP" '[$package,(.[] | .[$package][].version)]| @csv'

收到此错误
/print-version.sh GeoIP jq:error(at:34):无法在null(null)上迭代
“您提供的JSON未编译。请从末尾删除逗号3行。”
ilias sp已经告诉过您。我删除了逗号,仍然收到相同的错误消息。同一个输入文件这一个工作
cat output.json | jq-r--arg“package”“GeoIP”[$package,([].[$package][].version)]@csv'
我已经用示例中使用的output.json更新了我的答案。做出选择。使用shell的字符串插值是有风险的,通常被视为“反模式”。这很有帮助。