上篇文章介绍了jsawk,由于一些不足,这里又发现了一个更好的工具: jq
安装:
1 |
yum install -y jq |
用法:
1 |
man jq |
体验一下:
项目主页: https://stedolan.github.io/jq/
指南: https://stedolan.github.io/jq/tutorial/
手册: https://stedolan.github.io/jq/manual/
字符串连接
1 2 3 |
# echo '[{"from":"1","to":"2"},{"from":"1", "to":"2"}]'|jq -r '.[]| .from + ":" + .to' 1:2 1:2 |
(注意: 这里连接的是字符串,数字是不能直接当做字符串进行连接的)
类型转换:
1 2 3 4 5 |
# echo '[{"ID":1,"Name":"N1"},{"ID":2,"Name":"N2"}]'|jq '(.[].ID|tostring) + ":" + .[].Name' "1:N1" "2:N1" "1:N2" "2:N2" |
这里通过圆括号来单独处理一部分,然后通过tostring将输出内容转换为字符串; 也可以通过 @text 实现:
1 2 3 4 5 |
# echo '[{"ID":1,"Name":"N1"},{"ID":2,"Name":"N2"}]'|jq '(.[].ID|@text) + ":" + .[].Name' "1:N1" "2:N1" "1:N2" "2:N2" |
join:
1 2 3 |
# echo '[{"from":"1","to":"2"},{"from":"1", "to":"2"}]'|jq -r '.[]| join(":")' 1:2 1:2 |
获取对象的key:
1 2 3 |
# echo '{"a":"A", "b":"B"}'|jq -r 'to_entries[].key' a b |
等效于
1 2 3 |
# echo '{"a":"A", "b":"B"}'|jq -r 'to_entries[] |.key' a b |
等效于:
1 2 3 |
# echo '{"a":"A", "b":"B"}'|jq -r 'to_entries | .[] |.key' a b |
过滤:(通过select 过滤出Name为default的条目,然后只显示名字和ID列)
1 2 3 |
# openstack security group list -fjson|jq '.[]|select(.Name == "default")|.Name + ":" + .ID' "default:02dadaae-9d78-45ba-8fe5-496841b3c839" "default:1bfd33d7-6278-4718-9680-fd6f3328561d" |
错误的写法: (下面这个写法把Name和ID排列组合输出了)
1 |
openstack security group list -fjson|jq '.[].Name + ":" + .[].ID' |
如:
1 2 3 4 5 |
# echo '[{"ID":"1","Name":"N1"},{"ID":"2","Name":"N2"}]'|jq '.[].ID + ":" + .[].Name' "1:N1" "2:N1" "1:N2" "2:N2" |
根据path 和 select获取感兴趣的值:
1 2 3 4 5 |
# ceph status -f json|jq '(paths | select( .[-2:] == ["metadata", "ceph_version"])) as $path| getpath($path)' "ceph version 12.2.1 (3e7492b9ada8bdc9a5cd0feafd42fbca27f9c38e) luminous (stable)" "ceph version 12.2.1 (3e7492b9ada8bdc9a5cd0feafd42fbca27f9c38e) luminous (stable)" "ceph version 12.2.1 (3e7492b9ada8bdc9a5cd0feafd42fbca27f9c38e) luminous (stable)" "ceph version 12.2.1 (3e7492b9ada8bdc9a5cd0feafd42fbca27f9c38e) luminous (stable)" |
参考: https://stackoverflow.com/questions/25780807/can-i-use-a-relative-path-or-a-wildcard-in-jq
关联数组的key需要使用双引号,不能使用单引号:
1 2 |
# echo '{"a":"A", "b":"B"}'|jq -r '.["a"]' A |
1 2 3 4 |
# echo '{"a":"A", "b":"B"}'|jq -r ".['a']" jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at <top-level>, line 1: .['a'] jq: 1 compile error |
修改部分值
1 2 |
# echo '{"a":"A", "b":"B"}'|jq '.a="AA"' -c {"a":"AA","b":"B"} |
1 2 |
# echo '{"a":"A", "b":"B"}'|jq '.a="AA"|.b="BB"' -c {"a":"AA","b":"BB"} |
在任何一个级别中查找指定字段:
1 |
echo '[[{"a":1}]]' | jq ´..|.a?´ |
构造新对象:
关于paths的用法: 1.3 版本中还没有paths:
这里的paths放在圆括号内,不影响输出,就好比bash中的圆括号是在单独子进程中执行一样,不影响当前的环境,同时,使用as使得圆括号的输出保存在变量中,不影响后续的输入; 这样,使得getpath所在环境中的 dot 依然是原始的输入
参考资料: https://linuxtoy.org/archives/jq.html
https://github.com/stedolan/jq/issues/885
在线测试: https://jqplay.org/jq?
注意事项:
- 字符串只能使用双引号,不能使用单引号
- if 语句必须有else, 如果其中一个分支实在没啥说的就 select(false) 相当于empty