首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

命令行 JSON 处理工具 jq 的使用介绍-2

命令行 JSON 处理工具 jq 的使用介绍-2

基础表达式基础表达式(Basic filters)是 jq 提供的基本过滤器,用来访问 JSON                对象中的属性。基础表达式也是实现更复杂查询功能的基础。基础表达式主要有以下几种:
  • '.' 符号。单独的一个'.'符号用来表示对作为表达式输入的整个 JSON 对象的引用。
  • JSON 对象操作。jq 提供两种基本表达式用来访问 JSON                    对象的属性:'.<attributename>'和'.<attributename>?'。正常情况下,这两个表达式的行为相同:都是访问对象属性,如果                    JSON 对象不包含指定的属性则返回 null。区别在于,当输入不是 JSON                    对象或数组时,第一个表达式会抛出异常。第二个表达式无任何输出。
  • 数组操作。jq 提供三种基础表达式来操作数组:
    • 迭代器操作('.[]'). 该表达式的输入可以是数组或者 JSON 对象。输出的是基于数组元素或者 JSON 对象属性值的                            iterator。
    • 访问特定元素的操作('.[index]'或'.[attributename]')。用来访问数组元素或者 JSON                            对象的属性值。输出是单个值
    • 数组切片操作('.[startindex:endindex]'),其行为类似于 python 语言中数组切片操作。
  • 表达式操作(','和                    '|')。表达式操作是用来关联多个基础表达式。其中逗号表示对同一个输入应用多个表达式。管道符表示将前一个表达式的输出用作后一个表达式的输入。当前一个表达式产生的结果是迭代器时,会将迭代器中的每一个值用作后一个表达式的输入从而形成新的表达式。例如'.[]|.+1',                    在这个表达式中,第一个子表达式'.[]'在输入数组上构建迭代器,第二个子表达式则在迭代器的每个元素上加 1。
内置运算支持jq 内部支持的数据类型有:数字,字符串,数组和对象(object)。并且在这些数据类型的基础上, jq                提供了一些基本的操作符来实现一些基本的运算和数据操作。列举如下:
  • 数学运算。对于数字类型,jq 实现了基本的加减乘除(/)和求余(%)运算。对于除法运算,jq 最多支持 16 位小数。
  • 字符串操作。jq 提供字符串的连接操作(运算符为'+',例如:"tom "+"jerry"结果为"tom                    jerry"),字符串的复制操作(例如:'a'*3                    结果为'aaa'),以及字符串分割操作(将字符串按照指定的分割符分成数组,例如"sas"/"s"的结果为["","a",""],而"sas"/"a"的结果为["s","s"]。
  • 数组操作。jq 提供两种数组运算:并集('+')运算,结果数组中包含参与运算的数组的所有元素。差集运算('-'),例如:有数组 a,b,                    a-b 的结果为所有在 a 中且不包含在 b 中的元素组成的数组。
  • 对象操作。jq 实现了两个 JSON                    对象的合并操作(merge)。当两个参与运算的对象包含相同的属性时则保留运算符右侧对象的属性值。有两种合并运算符:'+'和'*'。所不同的是,运算符'+'只做顶层属性的合并,运算符'*'则是递归合并。例如:有对象                    a={"a":{"b":1}}, b={"a":{"c":2}},a+b 的结果为{"a":{"c":2}},而 a*b                    的结果为{"a":{"b":1,"c":2}}
  • 比较操作:jq 内部支持的比较操作符有==, !=,>,>=,<=和<。其中,'=='的规则和 javascript                    中的恒等('===')类似,只有两个操作数的类型和值均相同时其结果才是 true。
  • 逻辑运算符: and/or/not。在 jq 逻辑运算中,除了 false 和 null 外,其余的任何值都等同于 true。
  • 默认操作符('//'), 表达式'a//b'表示当表达式 a 的值不是 false 或 null 时,a//b 等于 a,否则等于                    b。
jq                中有一种很特殊的运算规则:当运算符的一个或两个操作数是迭代器时,其运算以类似与笛卡尔乘积的方式进行,即把两个操作数中的每一个元素拿出来分别运算。例如:
清单 3. 迭代器运算
1
2
#result is 5 6 7 8
jq -n '([1,2]|.[])+([4,6]|.[])'




jq 内部支持两种控制结构:判断语句和异常处理. 判断语句的完整结构为 if then-elif then-else-end.                当判断条件的结果为多个值时(迭代器),会对每个值执行一次判断。
异常处理语句的结构为 try <表达式 a> catch <表达式 b>. 当表达式 a 发生异常时,执行表达式                b,且输入为捕捉到的异常信息。如果不需要额外的处理,只是简单的抑制异常信息的输入,可以没有 catch 语句(如 try                .a)。这时,整个表达式可以简写为'<表达式 a>?'(如:.a?)。
jq 内部还支持函数。在使用 jq                函数时,我们应该注意区分两个概念:输入和参数。输入可能是整个表达式的输入数据也可能是表达式别的部分的输出。而参数和函数一起构成新的 filter                来处理输入。和其他编程语言不同的是,在调用函数时,多个参数之间以分号分隔。jq                通过内置函数提供了数据处理时常用的操作,例如:过滤,映射,路径操作等。下面分别说明。
映射操作在数据处理过程中,我们经常需求将数据从一种形式转换成另外一种形式,或者改变数据的值。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 高级特性
返回列表