在写 shell 脚本的时候遇到需要处理 json 数据,于是找到这款神奇的小工具 jq ,这里的 jq 不是 jquery 而是一款非常强大的 Linux 小工具,jq 的官网是:https://stedolan.github.io/jq/download/

首先,我们要使用它就需要先安装,可以去它的官网下载安装也可以使用下列命令进行安装

# Linux 使用 apt-get 安装
sudo apt-get install jq

# Mac OS 使用 brew 安装
brew install jq

当然我们如果写 shell 脚本的话可以先判断这个程序是否存在,不存在的话自动安装,如下是我写的一个判断方法,在 Mac OS 可使用,原理大致如下其他系统可以自行探索

# 判断 jq 是否安装
is_code_app_112233="jq"
if ! [ -x "$(command -v $is_code_app_112233)" ]; then
  # echo "Error: $appName is not installed." >&2
  if ! [ -x "$(command -v brew)" ]; then
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  fi
  brew install "$is_code_app_112233"
fi

# TOOD …判断存在则继续执行…

安装后怎么使用呢?先看看它的指令

--version
输出 jq 版本并退出。

--seq
使用application/json-seqMIME类型方案在jq的输入和输出中分隔JSON文本。这意味着将在输出的每个值之前打印一个ASCII RS(记录分隔符)字符,并在每个输出之后打印一个ASCII LF(换行)字符。无法解析的输入JSON文本将被忽略(但会发出警告),并丢弃所有后续输入,直到下一个RS。此模式还解析不带--seq选项的jq的输出。

--stream
以流方式解析输入,输出路径和叶值数组(标量和空数组或空对象)。例如,"a"变[[],"a"],并且[[],"a",["b"]]成为[[0],[]],[[1],"a"],和[[1,0],"b"]。
这对于处理非常大的输入很有用。将此与过滤以及the reduce和foreach语法结合使用,可逐步减少大输入。

--slurp/ -s
不必为输入中的每个JSON对象运行筛选器,而是将整个输入流读入一个大数组,然后仅运行筛选器一次。

--raw-input/ -R
不要将输入解析JSON。相反,每一行文本都作为字符串传递到过滤器。如果与组合--slurp,则整个输入将作为单个长字符串传递到过滤器。

--null-input/ -n
根本不读任何输入!而是将过滤器null作为输入运行一次。当将jq用作简单计算器或从头开始构造JSON数据时,这很有用。

--compact-output/ -c
默认情况下,jq pretty-prints JSON输出。通过将每个JSON对象放在一行上,使用此选项将导致输出更紧凑。

--tab
为每个缩进级别用一个选项卡,而不是两个空格。

--indent n
使用给定的空格数(不超过8个)进行缩进。

--color-output/ -C 和 --monochrome-output/ -M
默认情况下,如果写入终端,jq将输出彩色的JSON。即使使用写入管道或文件-C,也可以强制其产生颜色,并使用禁用颜色-M。
可以使用JQ_COLORS环境变量配置颜色。

--ascii-output/ -a
jq通常将非ASCII Unicode代码点输出为UTF-8,即使输入将其指定为转义序列(例如“ \ u03bc”)也是如此。使用此选项,您可以强制jq产生纯ASCII输出,并用等效的转义序列替换每个非ASCII字符。

--unbuffered
在打印每个JSON对象之后刷新输出(如果将慢速数据源输送到jq并将jq的输出输送到其他位置,则很有用)。

--sort-keys/ -S
用键按顺序输出每个对象的字段。

--raw-output/ -r
使用此选项,如果过滤器的结果是字符串,则将其直接写入标准输出,而不是将其格式化为带引号的JSON字符串。这对于使jq过滤器与基于非JSON的系统进行通信很有用。

--join-output/ -j
就像,-r但是jq在每个输出之后不会打印换行符。

-f filename/ --from-file filename
从文件而不是从命令行读取过滤器,如awk的-f选项。您也可以使用“#”发表评论。

-Ldirectory/ -L directory
前置directory为模块搜索列表。如果使用此选项,则不使用内置搜索列表。请参阅下面的模块部分。

-e/ --exit-status
设置为0 JQ的退出状态,如果最后输出值既不false也不null,1,如果最后的输出值要么false或null或4,如果没有有效的结果是以往任何时候产生的。通常,如果存在任何使用问题或系统错误,jq退出时为2;如果存在jq程序编译错误,则退出3;如果运行jq程序,则退出0。
设置退出状态的另一种方法是使用halt_error内置功能。

--arg name value
此选项将值作为预定义变量传递给jq程序。如果使用来运行jq --arg foo bar,则$foo该程序在程序中可用并且具有值"bar"。请注意,value它将被视为字符串,因此--arg foo 123将绑定$foo到"123"。
命名参数也可用于jq程序$ARGS.named。

--argjson name JSON-text
此选项将JSON编码的值作为预定义变量传递给jq程序。如果使用来运行jq --argjson foo 123,则$foo该程序在程序中可用并且具有值123。

--slurpfile variable-name filename
此选项读取命名文件中的所有JSON文本,并将已解析的JSON值数组绑定到给定的全局变量。如果使用来运行jq --slurpfile foo bar,则$foo该程序中可用,并且有一个数组,其元素对应于名为的文件中的文本bar。

--rawfile variable-name filename
此选项读取命名的文件,并将其内容绑定到给定的全局变量。如果使用来运行jq --rawfile foo bar,则$foo该程序中可用,并且有一个字符串,其内容与名为的文件中的tex有关bar。

--argfile variable-name filename
不使用,使用--slurpfile代替。
(此选项类似于--slurpfile,但是当文件只有一个文本时,则使用该文本,否则使用文本数组--slurpfile。)

--args
其余参数是位置字符串参数。这些可作为到jq程序使用$ARGS.positional[]。

--jsonargs
其余参数是位置JSON文本参数。这些可作为到jq程序使用$ARGS.positional[]。

--run-tests [filename]
在给定文件或标准输入中运行测试。这必须是给出的最后一个选项,并且不支持所有前面的选项。输入由注释行,空行和程序行组成,后跟一个输入行,与预期一样多的输出行(每个输出一个)和一个终止的空行。编译失败测试从仅包含“ %% FAIL”的行开始,然后是包含要编译的程序的行,然后是包含要与实际值进行比较的错误消息的行。

我目录下有一个 app.json 如下:

{
    "name": "test",
    "AppID": "com.test",
    "DisplayName": "demo",
    "Version": "1.0",
    "Build": 1,
}

我用 jq 获取 name 可以这么来写:

jq -c .name ./app.json

你会发现这个参数是获取到了但是怎么带了引号,jq 如何去掉引号获取呢?(现在我演示一下如何获取一个类似:{"name":"zmide","id":1234} 中获取 name 并赋值到 shell 变量上 )

# 去掉引号获取可以使用 -r 模式,这里我用了管道符代替文件了
echo '{"name":"zmide","id":1234}' | jq -r .name

# 将获取到的值赋值到 name 变量
name=`echo '{"name":"zmide","id":1234}' | jq -r .name`
echo $name

好了这个小工具的基本使用我就讲到这里,更多强大的使用方法快去官网手册一探究竟吧:https://stedolan.github.io/jq/manual/