您的位置:首页 > 运维架构 > Shell

shell里的json超级工具 jq 高级用法介绍

2019-04-19 22:06 337 查看

Linux shell 环境下有个和google Gson 一样好用的JSON 数据处理工具jq.
最近发现用jq 来分析提取数据,简直太好用了,特别是用于处理shell环境下面的复杂数据结构时,显的很方便。

实际问题1: 如何获取mesos 网页上的mesos-agent host 名称。

如下图:

查询了mesos api, 发现可以/master/slaves 获取所有数据。
curl -s http://10.2.1.72:5050/master/slaves | jq | less

curl -s http://10.2.1.72:5050/master/slaves | jq ‘.slaves’ | jq [.[].hostname]

happy:tmp happy$ curl -s http://10.2.1.72:5050/master/slaves | jq ‘.slaves’ | jq [.[].hostname]
[
mesos-agent1.cityworks.cn”,
mesos-agent2.cityworks.cn”,
mesos-agent3.cityworks.cn
]

如果不用jq 这个专业的JSON处理工具,用传统的grep ,tr 命令也可以实现,但是效果差很多,稳定性差, 在复杂的条件下,不能确保每次结果都是正确的。
特别是目标没有明显的规律时,就很难操作.

下面是jq在不同平台的安装和用法举例

安装
在OS X上安装jq:

brew install jq

或者在Ubuntu上:

apt-get install jq

Centos上:yum install -y jq

Alpine Linux: apk add jq

下面内容来自国外网页翻译:
用法
jq是围绕过滤器构建的。 最简单的过滤器是。,它回应了它的输入,但很漂亮:
$ echo ‘{“hello”:{ “greetings”:“to you”}}’ | jq .
{
“hello”: {
“greetings”: “to you”
}
}

例如,当您点击JSON API时,它非常适合从curl打印输出。
正如编写良好的手册所指出的,最简单有用的过滤器是.field,它从每个记录中提取字段:
$ echo ‘{“hello”:{ “greetings”:“to you”}}’ | jq .hello
{
“greetings”: “to you”
}
我们也可以为嵌套哈希做.field1.field2:

$ echo ‘{“hello”:{ “greetings”:“to you”}}’ | jq .hello.greetings
“to you”

让我们在一些真正的输入上使用jq。 这是一个名为1.json的Slack日志:

[
{
“type”: “message”,
“user”: “U024HFHU5”,
“text”: “hey there”,
“ts”: “1385407681.000003”
},
{
“type”: “message”,
“user”: “U024HGJ4E”,
“text”: “right back at you”,
“ts”: “1385407706.000006”
}
]

要从1.json中拉出每个Slack消息中的文本,我们需要首先使用。.[]进入“数组”。 然后我们可以使用|将数组中的每个对象传递给下一个过滤器,并使用.text从每个对象中获取文本字段:

$ jq “.[] | .text” 1.json
“hey there”
“right back at you”
Note that we now have plain-text representations of each value, so we could go back to sed:

$ jq “.[] | .text” 1.json | sed ‘s/h/H/g’
“Hey tHere”
“rigHt back at you”

转换输入
到目前为止,我们一直在拔出字段并显示它们。 现在让我们在显示它之前转换JSON。 让我们展示用户和文字:
$ jq “.[] | { the_user: .user, the_text: .text }” 1.json
{
“the_user”: “U024HFHU5”,
“the_text”: “hey there”
}
{
“the_user”: “U024HGJ4E”,
“the_text”: “right back at you”
}
.[]进入数组,给我们一个对象数组。 然后我们使用|将这些对象传递给下一个过滤器,并使用{}过滤器使用每个对象的字段构造一个新对象。 我们还将用户重命名为the_user,将文本重命名为the_text。

要在数组中包装内容,请在表达式周围加上括号:

$ jq “[.[] | { the_user: .user, the_text: .text }]” 1.json
[
{
“the_user”: “U024HFHU5”,
“the_text”: “hey there”
},
{
“the_user”: “U024HGJ4E”,
“the_text”: “right back at you”
}
]
请注意,我们将整个表达式包装在[]中,而不仅仅是{}部分。 如果我们将{}部分包装在方括号中,那么会将每个对象放在一个单独的数组中,这通常是我们不想要的:

$ jq “.[] | [{ the_user: .user, the_text: .text }]” 1.json
[
{
“the_user”: “U024HFHU5”,
“the_text”: “hey there”
}
]
[
{
“the_user”: “U024HGJ4E”,
“the_text”: “right back at you”
}
]

处理多个文件
假设我们有另一个JSON文件,2.json:

[
{
“type”: “message”,
“user”: “U028H5EBL”,
“text”: “<@U02A8N1DS>: Can I get some help with a domain registration?”,
“ts”: “1418301403.001783”
},
{
“type”: “message”,
“user”: “U02A8N1DS”,
“text”: “Sure thing.”,
“ts”: “1418301427.001784”
}
]
我们希望打印出来自1.json和2.json的所有消息,包装在一个数组中,就像我们之前一样。 让我们对两个文件运行相同的过滤器:

$ jq “.[] | [{ the_user: .user, the_text: .text }]” 1.json 2.json
[
{
“the_user”: “U024HFHU5”,
“the_text”: “hey there”
}
]
[
{
“the_user”: “U024HGJ4E”,
“the_text”: “right back at you”
}
]
[
{
“the_user”: “U028H5EBL”,
“the_text”: “<@U02A8N1DS>: Can I get some help with a domain registration?”
}
]
[
{
“the_user”: “U02A8N1DS”,
“the_text”: “Sure thing.”
}
]
嘿,这不好:每个文件的输出都包含在自己的数组中! 我们希望整个输出周围有一个数组,而不是每个文件一个数组。 幸运的是,jq有一个选项:jq --slurp将在1.json和2.json中汇总消息数组并将它们作为一个巨大数组处理。

让我们看看–slurp在我们对其输出做任何事情之前会产生什么:

$ jq --slurp . 1.json 2.json
[
[
{
“type”: “message”,
“user”: “U024HFHU5”,
“text”: “hey there”,
“ts”: “1385407681.000003”
},
{
“type”: “message”,
“user”: “U024HGJ4E”,
“text”: “right back at you”,
“ts”: “1385407706.000006”
}
],
[
{
“type”: “message”,
“user”: “U028H5EBL”,
“text”: “<@U02A8N1DS>: Can I get some help with a domain registration?”,
“ts”: “1418301403.001783”
},
{
“type”: “message”,
“user”: “U02A8N1DS”,
“text”: “Sure thing.”,
“ts”: “1418301427.001784”
}
]
]

正如我们所看到的,它将所有输入包装在一个大数组中,因此我们将在过滤时添加额外的.[]以获取内部对象:
$ jq --slurp “[.[] | .[] | { text: .text }]” 1.json 2.json
[
{
“text”: “hey there”
},
{
“text”: “right back at you”
},
{
“text”: “<@U02A8N1DS>: Can I get some help with a domain registration?”
},
{
“text”: “Sure thing.”
}
]

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: