jq命令@shell
所有操作默认非root用户,本文中用 zhe.lin
用户。
jq
jq
命令是Linux下的一个命令,mac用户可以用brew install jq
来安装
jq
通过 jq表达式 来对Json格式的数据做处理,接下来的操作以此Json文本(json.txt
)作为输入:
{"person":[{"firstname":"Z","lastname":"L"},{"firstname":"M","lastname":"J"}],"game":{"name":"yys"}}
基本jq操作
现在对这个文件使用jq
命令 cat Json.txt | jq .
:
{
"person": [
{
"firstname": "Z",
"lastname": "L"
},
{
"firstname": "M",
"lastname": "J"
}
],
"game": {
"name": "yys"
}
}
可以看到jq支持从管道操作符|
接受输入,'.'
是一个最简单的jq表达式,他表示选取这个Json并什么都不做
接下来做一个选取操作cat Json.txt | jq .person
。另外jq表达式内也支持|
操作符进行串行化操作,管道前面表达式的输出可以作为管道后表达式的输入,所以上面的命令也可以写成cat Json.txt | jq '. | .person'
(为了防止歧义这里将整个jq表达式用单引号’‘包住了),这两个命令可以得到相同的输出 :
[
{
"firstname": "Z",
"lastname": "L"
},
{
"firstname": "M",
"lastname": "J"
}
]
可以看到.person
代表选取这个Json中key为person
的元素,它是一个Json数组。
类似.[]
的表达式可以操作数组(也就是上一个命令的输出),这个命令的输入既可以是数组也可以是Json对象,输出的是基于数组元素或对象属性值(只有value没有key)的迭代器。一个表达式产生的结果是迭代器时,迭代器的每一个值会分别作为的输入,传给后面的表达式。以cat Json.txt | jq '.person | .[]'
命令为例 :
{
"firstname": "Z",
"lastname": "L"
}
{
"firstname": "M",
"lastname": "J"
}
注意上述输出既没有代表数组的[]
,同时两个Json对象之间也没有,
分隔。
特别注意:对于.[]
命令,如果输入是一个数组,返回的是一个数组里每个元素的迭代器;如果输入是一个Json对象,则生成的迭代器里只有values没有keys
验证命令1 cat Json.txt | jq '.game | .[]'
:
"yys"
验证命令2 cat Json.txt | jq '.person | .[]'
:
{
"firstname": "Z",
"lastname": "L"
}
{
"firstname": "M",
"lastname": "J"
}
用.[index]
或.[attributename]
可以访问数组元素或者Json对象的属性值。以cat Json.txt | jq '.person | .[0]'
为例演示index访问:
{
"firstname": "Z",
"lastname": "L"
}
可以看到index是从 0 开始的;接下来以cat Json.txt | jq '.person | .[0] | .["firstname"]'
演示attributename访问 :
"Z"
- 事实上以下两种写法也能达到相同效果:
cat Json.txt | jq '.person | .[0] | .firstname'
cat Json.txt | jq '.person | .[0].firstname'
.[startindex:endindex]
可以实现数组切片操作,返回仍然是一个数组,以cat Json.txt | jq '.person | .[0:1]'
为例,可以看到下标是左闭右开 :
[
{
"firstname": "Z",
"lastname": "L"
}
]
jq函数
删除
用法:jq expr | del(jq_expr)
命令cat Json.txt | jq '. | del(.person)'
:
{
"game": {
"name": "yys"
}
}
映射
用法:map(jq_expr)
To Be Continued…
过滤
用法:jq expr | select(jq_expr)
命令cat Json.txt | jq '.["person"] | .[] | select(.lastname=="L")'
:
{
"firstname": "Z",
"lastname": "L"
}
命令cat Json.txt | jq '.["person"] | .[] | select(.lastname=="J")'
:
{
"firstname": "M",
"lastname": "J"
}
命令cat Json.txt | jq '.["person"] | .[] | select(.lastname=="l")'
:
数组函数
sort / sort_by / reverse
排序
用法:jq expr | sort
命令cat Json.txt | jq '.["person"] | sort'
:
[
{
"firstname": "M",
"lastname": "J"
},
{
"firstname": "Z",
"lastname": "L"
}
]
注意此命令后,数组内MJ位于ZL之前了,说明顺序的确被替换了。
正则表达式
jq正则表达式以如下语法出现:
STRING | FILTER( REGEX )
STRING | FILTER( REGEX; FLAGS )
STRING | FILTER( [REGEX] )
STRING | FILTER( [REGEX, FLAGS] )
其中FILTER
可以是test / match / capture
,FLAGS
暂且按下不表,以下分别展开说
test
test()
只返回真假
用法jq expr | test( REGEX )
命令cat Json.txt | jq '.game.name | test(".ys$")'
true
命令cat Json.txt | jq '.game | select(.name | test("ys$"))'
:
{
"name": "yys"
}
命令cat Json.txt | jq '.game | select(.name | test("^ys$"))'
:
众所周知^
匹配字符串开头,$
匹配字符串结尾,所以test("ys$")
返回真而test("^ys$")
返回假,配合select()
可以完成从Json中匹配正则表达式的能力
—
match
类似test
,只不过match
返回的不再是真/假,而是返回匹配上的对象
用法jq expr | match( REGEX )
命令cat Json.txt | jq '.game.name | match(".*s$")'
{
"offset": 0,
"length": 3,
"string": "yys",
"captures": []
}
capture
太复杂了,自己体会吧…
大概是让你分段匹配
命令cat Json.txt | jq '.game.name | capture("(?<left>[a-z]+)y(?<right>[a-z]+)")'
{
"left": "y",
"right": "s"
}