命令行 JSON 处理工具 jq 的使用介绍(3)

在数据处理过程中,我们经常需求将数据从一种形式转换成另外一种形式,或者改变数据的值。jq 提供了两个内置映射函数来实现这种转换:map 和 map_values。其中,map 处理的对象是数组,而 map_values 则处理对象属性的值。map 函数的参数为 filter 表达式。在该 filter 表达式中,'.'代表被映射的元素或值。

清单 4. map 函数

1

2

3

 

输入:[1,2,3,4]

jq 表达式:jq -r 'map(.+1)'

输出:[2,3,4,5]

 

过滤操作

在 jq 中有两种类型的选择过滤操作。第一种是基于数据类型的过滤,如表达式'.[]|arrays'的结果只包含数组。可以用来过滤的类型过滤器有:arrays, objects, iterables, booleans, numbers, normals, finites, strings, nulls, values, scalars。

第二种是 select 函数。select 接受一个条件表达式作为参数。其输入可以是迭代器,或者和 map 函数配合使用来处理数组。当输入中的某个元素使 select 参数中的条件表达式结果为真时,则在结果中保留该元素,否则不保留该元素。

清单 5. select 函数

1

2

3

4

5

 

输入:[1,2,3,4]

表达式:jq -r 'map(select(.>2))'

输出:[3,4]

表达式:jq -r '.[]|select(.>2)'

输出:3 4

 

路径操作

和 xpath 类似,在 jq 中的 path 也是指从根到某个叶子属性的访问路径。在 jq 中有两种表示路径的方式:数组表示法和属性表示法。属性表示法类似于我们在 filter 中访问某个属性值的方式,如'.a.b'。数组表示法是将路径中的每一部分表示为数组的一个元素。jq 提供了一个内置函数 path 用来实现路径从属性表示法到数组表示法的转换。

jq 还提供了函数用来读取路径的值(getpath), 设置路径的值(setpath)和删除路径(del)。不过遗憾的是,这三个函数对路径的处理并不一致。其中 getpath 和 setpath 只接受数组表示法的路径,而 del 函数只能正确处理属性表示法的路径。

jq 还提供了一个函数 paths 用来枚举可能存在的路径。在没有参数的情况下,paths 函数将输出 JSON 数据中所有可能的路径。paths 函数可以接受一个过滤器,来只输出满足条件的路径。

存在判断函数

jq 中提供了一系列的函数用来判断某个元素或者属性是否存在于输入数据中。其中函数 has 和 in 用来判断 JSON 对象或数组是否包含特定的属性或索引。函数 contains 和 inside 用来判断参数是否完全包含在输入数据中。对于不同的数据类型,判断是否完全包含的规则不同。对于字符串,如果 A 是 B 的子字符串,则认为 A 完全包含于 B。对于对象类型,如果对象 A 的所有属性在对象 B 中都能找到且值相同,则认为 A 完全包含于 B。

数组函数

除了前面讲述的基本操作符外,jq 提供内置函数用于完成数组的扁平化(flatten),反序(reverse),排序(sort, sort_by),比较(min,min_by,max,max_by)和查找(indices,index 和 rindex)。其中 indices 函数的输入数据可以是数组,也可以是字符串。和 index 函数不同的是,其结果是一个包含所有参数在输入数据中位置的数组,具体请参看下面的例子。

清单 6. jq 中的数组函数

1

2

3

4

5

6

7

8

9

 

#结果是[1,2,3,4]

jq -nr '[1,[2,3],4]|flatten'

#结果是[3,2,1]

jq -nr '[1,2,3]|reverse'

jq -nr '[3,1,2]|sort'

jq -nr '[{"a":1},{"a":2}]|sort_by(.a)'

#下面两个表达式的结果都是[1,3]

jq -nr '"abcb"|indices("b")'

jq -nr '[1,3,2,3]|indices(3)'

 

jq 还提供了许多其他的内置函数,具体请参考 jq 的在线文档。

jq 高级特性 变量

jq 内部支持两种变量的定义方式。第一种我们在前边 jq 的调用部分讲过,可以通过命令行参数(--arg)定义。这种方式用来从外部(如:shell)传入数据以供 filter 表达式使用。

第二种方式,在 jq 表达式内部,我们可以自己声明变量用来保存表达式的结果以供表达式其余部分使用。

jq 中定义变量的语句为: fiterexp as $variablename

清单 7.定义和使用变量

1

2

3

4

 

#在下面的表达式中变量$arraylen 用来保存数组长度,整个表达式结果为 4

jq -nr '[1,2,3]|length as $arraylen|$arraylen+1'

#可以同时定义多个变量

jq -nr '{"firstname":"tom","lastname":"clancy"}|. as {firstname:$fn, lastname:$ln}|"author is "+$fn+"*"+$ln'

 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzdxdg.html