Abel'Blog

我干了什么?究竟拿了时间换了什么?

0%

jq 完全教程

简介

下面这份文档适合作为技术博客文章,覆盖了 jq 从入门到实战的大部分常用场景,并且尽量结合 DevOps、区块链节点运维、日志分析等实际工作场景。

jq 完全教程:JSON 处理神器从入门到实战

什么是 jq

jq 是 Linux/macOS 下最强大的 JSON 命令行处理工具。

如果说:

  • grep 处理文本
  • awk 处理表格
  • sed 处理字符串

那么:

jq 就是专门处理 JSON 的神器。

官方网站:

https://jqlang.org

安装:

macOS

brew install jq

Ubuntu

sudo apt install jq

CentOS

yum install jq

验证:

jq –version

输出:

jq-1.7

为什么要学习 jq

现代开发中到处都是 JSON:

  • REST API
  • Kubernetes
  • Docker
  • Prometheus
  • Ethereum RPC
  • Solana RPC
  • Elasticsearch
  • Cloudflare API

例如:

{
“jsonrpc”:”2.0”,
“id”:1,
“result”:”0x1d4c”
}

不用 jq:

curl xxx

输出一坨:

{“jsonrpc”:”2.0”,”id”:1,”result”:”0x1d4c”}

使用 jq:

curl xxx | jq

变成:

{
“jsonrpc”: “2.0”,
“id”: 1,
“result”: “0x1d4c”
}

瞬间舒服。

基本语法

jq 的基本形式:

jq ‘

例如:

cat data.json | jq ‘.’

表示:

输出整个 JSON

读取字段

假设:

{
“name”:”Tom”,
“age”:18
}

读取:

jq ‘.name’

输出:

“Tom”

读取年龄:

jq ‘.age’

输出:

18

去掉双引号

默认:

jq ‘.name’

输出:

“Tom”

很多脚本不方便。

使用:

jq -r ‘.name’

输出:

Tom

-r

表示:

raw output

这是最常用参数之一。

多层 JSON

例如:

{
“user”: {
“name”: “Tom”,
“age”: 18
}
}

读取:

jq ‘.user.name’

输出:

“Tom”

数组操作

JSON:

{
“users”: [
{“name”:”Tom”},
{“name”:”Jack”},
{“name”:”Lucy”}
]
}

读取第一个:

jq ‘.users[0]’

输出:

{
“name”:”Tom”
}

读取名称:

jq ‘.users[0].name’

输出:

“Tom”

遍历数组

例如:

jq ‘.users[]’

输出:

{
“name”:”Tom”
}
{
“name”:”Jack”
}
{
“name”:”Lucy”
}

只输出名称:

jq -r ‘.users[].name’

输出:

Tom
Jack
Lucy

数组长度

jq ‘.users | length’

输出:

3

获取最后一个元素

jq ‘.users[-1]’

输出:

{
“name”:”Lucy”
}

条件过滤

数据:

[
{“name”:”Tom”,”age”:18},
{“name”:”Jack”,”age”:25},
{“name”:”Lucy”,”age”:30}
]

筛选:

jq ‘.[] | select(.age > 20)’

输出:

{
“name”:”Jack”,
“age”:25
}
{
“name”:”Lucy”,
“age”:30
}

多条件过滤

jq ‘.[] | select(.age > 20 and .age < 30)’

输出:

{
“name”:”Jack”,
“age”:25
}

字段存在判断

jq ‘has(“name”)’

输出:

true

提取多个字段

例如:

{
“name”:”Tom”,
“age”:18,
“city”:”Shanghai”
}

输出:

jq ‘{name,age}’

结果:

{
“name”:”Tom”,
“age”:18
}

重命名字段

jq ‘{username:.name,userage:.age}’

输出:

{
“username”:”Tom”,
“userage”:18
}

修改字段

原始:

{
“name”:”Tom”,
“age”:18
}

修改:

jq ‘.age=20’

输出:

{
“name”:”Tom”,
“age”:20
}

删除字段

jq ‘del(.age)’

结果:

{
“name”:”Tom”
}

排序

数据:

[
{“name”:”Tom”,”age”:30},
{“name”:”Jack”,”age”:18},
{“name”:”Lucy”,”age”:25}
]

按年龄:

jq ‘sort_by(.age)’

结果:

[
{
“name”:”Jack”,
“age”:18
},
{
“name”:”Lucy”,
“age”:25
},
{
“name”:”Tom”,
“age”:30
}
]

统计

求和:

jq ‘[.[].age] | add’

输出:

73

平均值:

jq ‘[.[].age] | add / length’

输出:

24.333333333333332

map

提取所有名称:

jq ‘map(.name)’

结果:

[
“Tom”,
“Jack”,
“Lucy”
]

实战:调用 RPC

获取区块高度:

curl -s
-H “Content-Type: application/json”
-d ‘{“jsonrpc”:”2.0”,”id”:1,”method”:”eth_blockNumber”,”params”:[]}’
https://rpc.consciousnesschain.com
| jq -r ‘.result’

输出:

0x1d4c

转换十进制:

curl … | jq -r ‘.result’ | xargs printf “%d\n”

实战:Docker

查看容器名称:

docker inspect container_id | jq ‘.[0].Name’

去掉双引号:

docker inspect container_id | jq -r ‘.[0].Name’

实战:Kubernetes

获取 Pod 名称:

kubectl get pods -o json
| jq -r ‘.items[].metadata.name’

获取所有镜像:

kubectl get pods -o json
| jq -r ‘.items[].spec.containers[].image’

实战:Prometheus

查询结果:

{
“status”:”success”,
“data”:{
“result”:[
{
“value”:[
1749700000,
“123”
]
}
]
}
}

获取指标值:

jq -r ‘.data.result[0].value[1]’

输出:

123

实战:日志分析

统计所有错误级别:

日志:

{“level”:”info”}
{“level”:”error”}
{“level”:”warn”}
{“level”:”error”}

统计:

jq -r ‘.level’ log.json
| sort
| uniq -c

输出:

2 error
1 info
1 warn

实战:调用 REST API

获取 GitHub 用户信息:

curl -s https://api.github.com/users/torvalds | jq

输出:

{
“login”: “torvalds”,
“id”: 1024025,

}

获取用户名:

curl -s https://api.github.com/users/torvalds
| jq -r ‘.login’

输出:

torvalds

获取仓库数量:

curl -s https://api.github.com/users/torvalds
| jq ‘.public_repos’

实战:Docker

查看容器名称:

docker inspect nginx
| jq -r ‘.[0].Name’

查看 IP:

docker inspect nginx
| jq -r ‘.[0].NetworkSettings.IPAddress’

查看挂载目录:

docker inspect nginx
| jq ‘.[0].Mounts’

实战:Kubernetes

查看所有 Pod:

kubectl get pods -o json
| jq -r ‘.items[].metadata.name’

查看所有镜像:

kubectl get pods -o json
| jq -r ‘.items[].spec.containers[].image’

查看 Pod 状态:

kubectl get pods -o json
| jq -r ‘.items[] | [.metadata.name,.status.phase] | @tsv’

输出:

api-server Running
mysql Running
redis Pending

实战:Prometheus

查询指标:

curl -s http://localhost:9090/api/v1/query
–data-urlencode ‘query=up’
| jq

获取指标值:

jq -r ‘.data.result[].value[1]’

实战:Nginx JSON 日志

日志:

{
“remote_addr”:”10.0.0.1”,
“status”:200,
“request_time”:0.023
}

筛选慢请求:

jq ‘select(.request_time > 1)’

筛选错误请求:

jq ‘select(.status >= 500)’

实战:统计日志等级

日志:

{“level”:”info”}
{“level”:”error”}
{“level”:”warn”}
{“level”:”error”}

统计:

jq -r ‘.level’ app.log
| sort
| uniq -c

输出:

2 error
1 info
1 warn

实战:配置文件检查

config.json:

{
“server”: {
“host”:”127.0.0.1”,
“port”:8080
}
}

查看端口:

jq ‘.server.port’ config.json

查看主机:

jq -r ‘.server.host’ config.json

实战:JSON 格式化工具

压缩:

jq -c .

输出:

{“name”:”Tom”,”age”:18}

美化:

jq .

输出:

{
“name”: “Tom”,
“age”: 18
}

实战:CSV 转换

JSON:

[
{“name”:”Tom”,”age”:18},
{“name”:”Jack”,”age”:20}
]

转换:

jq -r ‘.[] | [.name,.age] | @csv’

输出:

“Tom”,18
“Jack”,20

实战:生成 TSV

jq -r ‘.[] | [.name,.age] | @tsv’

输出:

Tom 18
Jack 20

总结

把最后一章改成:

jq 几乎会出现在所有现代基础设施中:

  • REST API
  • Docker
  • Kubernetes
  • Prometheus
  • Elasticsearch
  • Loki
  • Nginx JSON 日志
  • GitHub API
  • GitLab API
  • 各类配置文件

学会 jq 后,可以大幅提升 Linux 命令行处理 JSON 的效率。