目录
5. Builtin Operators And Functions(内置运算符和函数)
6. Conditionals And Comparisons(条件和比较)
0. Prefice(前言)
JQ是一个命令行工具,主要用于处理json文本。语法很简单,如下:
jq [options...] filter [files...]
JQ可以对json文本执行多种操作,包括选择、遍历、删减等等。例如 jq ´map(.price) | add´ 表示遍历输入的数组,并将其中每个元素的price累加起来。默认情况下,jq从stdin中读取json数据流,多个数据流使用空格分隔。还有一些命令行参数,主要用于控制输出和输出的格式,filter是jq语言编写的,主要用于操作输入的数据。
1. Filter(过滤器)
filter 相当于jq程序,有很多内置的filter用于从对象中提取字段、或者将一个数字转换为字符串或者其它的功能。
filter 可以用不同的方式组合,比如可以通过管道将一个filter的输出当做另一个filter的输入,或者收集一个filter的输出,存到一个数组里。有些filter能够生成多个结果,比如枚举出json数组中的每个元素,通过管道将元素依次传输给第二个filter。其它语言中通过循环和迭代实现的功能在jq中可以通过组合多个filter来实现。
2. Options(可选项)
--slurp/-s:
如果有多个json输入流,默认情况下,会对每个输入执行JQ命令,如果使用该参数,则会将所有输入放到一个数组里,然后执行一次JQ命令。
--raw-input/-R
默认情况下,输入必须是json格式文本,如果使用该选项,则将每行文本当做一个普通的字符串。
--null-input/-n
将null作为输入,该选项忽略任何输入,仅仅将null当做输入传给filter。正如下面的例子,如果没有null-input,这时候第一个参数是"one",因为没有任何操作会被忽略,"inputs"表示剩余的输入,因此第一个用例输出"two, three",如果使用了null-input,这时候忽略的就是参数null,其余输入就会被读取到"inputs"里面,如示例三。
--compact-output / -c:
默认情况下,jq 的输出是可读性好的格式,如果使用该选项,则输出则会变得紧凑。
--colour-output / -C
默认情况下,如果输出到stdout,是有颜色的。使用该选项可以强制输出颜色,即便是输出到管道或者文件中。
--monochrome-output / -M
禁止输出颜色
--ascii-output / -a:
非ASCII字符通常当做utf8字符输出,使用该选项可以强制输出ascii字符。
--raw-output / -r
如果输出是一个字符串,默认情况下对包含一对双引号,如果使用该选项,则仅仅输出字符串文本。
--arg name value
传递变量到jq程序里
3. Basic Filters(基础过滤器)
'.'
. 是最基本的过滤器,对输出不做任何处理,原样输出。通常用来输出一些可读性强的格式。
.Attr
Attr是JSON对象的属性名,这个过滤器用于打印指定key的值,如果不存在对应的key,则输出NULL
.[]
打印数组内容,括号内可以指定索引或者指定范围,索引从0开始。
,
可以使用逗号连接多个过滤器,这种情况下,每个过滤器分别执行,结果也会并列展示出来
|
管道符用于连接两个过滤器,功能上类似与Unix shell 管道,左侧过滤器执行结果会被当做右侧过滤器的输入,如果左侧过滤器产生多个结果,则右侧过滤器会分别执行。
4. Types And Values(数据类型和值)
jq支持和json一致的数据集,包括数字、字符串、布尔值、数组、对象和null
数组 []
和json一样,[]也用于构造一个数组,数组的元素可以是任意的jq表达式,表达式的结果将会组成一个数组,可以使用[]构造任何数组。
对象·{}
和json一样,{}用于构造对象,如果对象的key是大小写敏感的,则双引号可以省略,值可以是任意的jq表达式(如果是复杂的表达式,还需要使用括号括起来),可以使用这个符号从输入中选取指定的字段。如果某个表达式生成多个结果,则对象也可能生成多个。如果key被括号括起来,则key也会被当做一个表达式。
5. Builtin Operators And Functions(内置运算符和函数)
一些jq操作符(例如+),对根据参数的不同执行不同的操作(比如数组、数字、字符串等)。但是jq不会执行任何隐式的类型转换,如果两个参数类型不一致,会直接报错。
加号 +
加号需要两个filter,输入会分别被过滤器执行,输出结果会根据过滤器结果类型相加起来。
如果是数字,则按照算数相加。
如果是数组,则会拼接成一个大数组,
如果是字符串,则会拼接起来。
如果是对象,则对象会被合并,如果有相同的key,则以右侧的过滤器中的key为最终结果。
如果有一个结果是null,则返回另一个结果。
减号 -
和算术减法类似,减号也可以用在数组上,用于将数组1中所有在数组2中出现的元素删除。
乘法*、除法 /、取余%
这些操作符只作用于数字。
length
该函数获取不同类型值的长度。
如果是字符串,则输出unicode代码点数量。也可以使用utf8bytelength 输出字符数量
如果是数组,则输出数组元素个数
如果是对象,则输出key-value 组的个数
如果是null,则为0
keys
如果输入是个对象,则输出一个包含该对象所有key的数组。
如果输入是个数组,则输出该数组合法的索引。
has
has函数返回一个对象是否有指定的key,或者一个数组在指定的索引上是否含有元素。
to_entries, from_entries, with_entries
这些函数在对象和包含key-value的数组中转换,如果to_entries接受一个对象,则对于对象中每一个k:v,则输出的数组中将包含{"key": k, "value": v}.
from_entries 正好做相反的事情,with_entries 等价于 to_entries|map(foo)|from_entries
select
select(filter),如果filter返回true,则结果与输入一致,否则不输出。
empty
empty不返回任何结果,包括null也不返回。
map(filter)
map是个遍历操作,对输出数组的每个元素执行filter,并将输出放到一个数组里。等价于 '.[]|filter'
add
add函数将输入当做一个数组,根据数组的元素类型执行相应的操作,包括累加、字符串拼接、合并等。
range
range函数用于生成一组连续的数字,range(4;10)产生6个数字,从4开始,直到10(10本身不包括在内)。生成的数组将作为独立的输出。
tonumber
这是个类型转换函数,该函数将输入当做数字,如果输入不是标准的数字形式会报错。
tostring
同上,也是个类型转换函数,将输入当做字符串。
type
该函数将输入的类型当做字符串输出,可能是null,boolean、number、string、array、object的一种。
sort、sort_by
这是个排序函数,输入必须是数组类型。sort_by用于根据某一个字段来排序或者基于filter,sort_by(filter)会根据filter结果来进行排序。
group_by(.attr)
分组,类似于mysql,将输入当做一个数组,指定一个属性,具有相同值的会被分到同一个数组中。
min, max, min_by, max_by
前两个就是取最大值和最小值,后两个可以根据指定属性取。
unique
该函数输入是一个数组,输出一个不含重复元素的数组
reverse
函数用于将数组翻转
contains(v)
如果输入包含v,则该函数返回true。
recurse
该函数主要用于搜索递归类型结构数据。
字符串替换 \(x)
在一个字符串中,可以加入一个反斜杠开头的表达式:'\express',则这个表达式的结果将会插入到字符串中。
6. Conditionals And Comparisons(条件和比较)
== , !=
表达式==只有在两个参数完全相等时才返回true,其他情况返回FALSE,表达式!=与之相反。
if-then-else
表达式必须明确返回true或者FALSE,如果表达式返回false或者null会被当做false,如果返回0也是false.
>、>=、<=、<
这几个比较运算符和算术比较运算符逻辑类似,结果返回true或者false
and/or/not
布尔运算符,这里值得注意的地方是如果有一个操作数生成了多个结果,则运算符会针对每个结果运算一遍。
替代运算符 //
如果一个过滤器表达式以 a//b的形式出现,如果a的结果不是false和null,则该过滤器结果为a的结果,否则为b表达式的结果。这个表达式对于提供默认值非常有用。
7. Advanced Features(高级特性)
在其它编程语言中,变量是不可或缺的一部分。在JQ中,变量属于一种高级特性。在大部分语言里,变量是传递临时数据的唯一方式,如果你要计算一个值,并且之后在其它地方还要用到,你需要使用变量来存储它。为了给程序的其它函数传递值,你需要定义一个变量(作为函数参数等)。在jq中变量很少使用,但是也是可以定义的,主要用于定义一些标准库(很多jq函数就是这么实现的,比如map和find)。
jq还有一个reduce操作,很强大但是使用起来需要一点技巧。这个操作主要用于jq内部操作。
在jq中,我们可以使用表达式 exp as $x | .... 的方式来定义变量。对于exp生成的每一个值,都会单独执行后续的操作,这里的as就像一个遍历操作。
除了定义变量外,还可以使用def 语法定义函数。
reduce语法主要用于累积表达式生成的所有结果。