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

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

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

jq 简介JSON 是一种轻量级的数据交换格式。其采用完全独立于语言的文本格式,具有方便人阅读和编写,同时也易于机器的解析和生成。这些特性决定了 JSON                格式越来越广泛的应用于现代的各种系统中。作为系统管理员,在日常的工作中无论是编辑配置文件或者通过 http 请求查询信息,我们都不可避免的要处理                JSON 格式的数据。
jq 是一款命令行下处理 JSON 数据的工具。其可以接受标准输入,命令管道或者文件中的 JSON                数据,经过一系列的过滤器(filters)和表达式的转后形成我们需要的数据结构并将结果输出到标准输出中。jq 的这种特性使我们可以很容易地在                Shell 脚本中调用它。
jq 安装jq 是开源软件。目前大部分的 Linux 系统和 Unix                系统的官方软件仓库中均有收录。用户可以通过系统自带的软件包管理器直接安装,也可以手动从源代码编译安装。jq 的源代码可以从其代码仓库中获得。编译                jq 的指令如下:
清单 1. 编译 jq
1
2
3
4
5
6
git clone https://github.com/stedolan/jq.git
cd jq
autoreconf -i
./configure --disable-maintainer-mode
make
sudo make install




windows 用户可以通过 Chocolatey NuGet 安装或者直接从官网下载可执行文件。
开始使用 jq如何调用 jq作为一个标准的命令行工具,jq 支持"-h"选项(或者长格式"--help")。通过该选项,我们可以看到 jq 的简略的使用帮助。在 linux                系统中,我们可以通过 man 命令来查看 jq 详细文档。
jq 可以处理 JSON 文件,也可以直接处理从命令行管道或者流中传入的数据。这方便我们在 shell 脚本中使用。如下面代码:
图 1.jq                命令行帮助清单 2. jq                直接处理文件
1
2
3
4
#xxx.JSON 中是我们要处理的 JSON 数据,我们可以直接将文件名传给 jq
$ jq -r '.' xxx.JSON
#或者由其他程序读出文件内容,并传给 jq
$ cat xxx.JSON|jq -r '.'




需要说明的是 jq 只能接受 well form 的 JSON 字符串作为输入内容。也就是说输入内容必须严格遵循 JSON                格式的标准。所有的属性名必须是以双引号包括的字符串。对象的最后一个属性的末尾或者数组的最后一个元素的末尾不能有逗号。否则 jq 会抛出无法解析                JSON 的错误。
jq 通过命令行选项来控制对输入输出的处理。选项的具体内容请参见图一中的 jq 帮助。这里介绍几个比较常用和重要的选项。
  • '-r'选项。该选项控制 jq 是输出 raw 格式内容或 JSON 格式内容。所谓的 JSON 格式是指符合 JSON                    标准的格式。例如,假设我们要查询 JSON 字符串{"name":"tom"}中 name 的值. 使用-r 选项时返回的是'tom'.                    不使用-r 选项时,返回的是'"tom"'.返回值多了一对双引号。
  • -s 选项。 jq 可以同时处理空格分割的多个 JSON 字符串输入。默认情况下,jq 会将 filter 分别对每个 JSON                    输入应用,并返回结果。使用-s 选项,jq 会将所有的 JSON 输入放入一个数组中并在这个数组上使用 filter。"-s"选项不但影响到                    filter 的写法。如果在 filter 中需要对数据进行选择和映射,其还会影响最终结果。
  • --arg 选项。jq 通过该选项提供了和宿主脚本语言交互的能力。该选项将值(v)绑定到一个变量(a)上。在后面的 filter                    中可以直接通过变量引用这个值。例如,filter '.$a'表示查询属性名称等于变量 a 的值的属性。
jq 表达式从图 1 的 jq 帮助中我们可以看出,在调用 jq 处理 JSON 数据时有一个必须的部分"jq filters". 实际上,jq                内部构建了一个简易的,功能完备的语言系统。用户在使用 jq 时,需要使用 jq 支持的语法来构建表达式(filters)并将其传给 jq。 jq                根据语法规则解析表达式并应用在输入的 JSON 数据上从而得到需要的结果。
jq                表达式支持串行化操作。一个复杂的表达式可以有多个简单的,以"|"符号分割的,串行化执行的表达式组成。每个表达式以其前边表达式的结果为输入。例如:有                JSON 数据{"name":{"firstname":"Tom","lastname":"Clancy"}}。我们要查询 lastname                属性可以使用表达式'.name|.lastname'。为了方便处理 JSON 数据,jq 提供了以下几点特性支持:
  • jq 内建了对 JSON 标准中各种数据类型的支持
  • jq 内建了多种操作符和函数来进行数据的选择和转换。
  • jq 支持自定义函数和模块化系统。我们可以自定义自己的函数库,并在 jq 表达式中引用。
基础表达式基础表达式(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                通过内置函数提供了数据处理时常用的操作,例如:过滤,映射,路径操作等。下面分别说明。
返回列表