简介
jq 命令是一个轻量且灵活的命令行 JSON 处理器,可以方便快捷地解析 JSON 格式的数据。
基本用法
解析 JSON 格式的数据
1
| cat task_feature_file | jq .
|
根据 key 获取 value
1
| cat task_feature_file | jq '.cms_data'
|
根据 key 获取 value(嵌套提取)
1
| cat task_feature_file | jq '.cms_data.res_id'
|
提取所有 key
1
| cat task_feature_file | jq 'keys'
|
提取所有 key(嵌套提取)
1
| cat task_feature_file | jq '.cms_data' | jq 'keys'
|
判断是否有某个 key
1
| cat task_feature_file | jq 'has("cms_data")'
|
数据转换
转换数字为字符串
1 2 3 4 5 6 7
| jq -r '.[] | [ .string, .number|tostring ] | join(": ")' <<< ' [{ "number": 9, "string": "nine"}, { "number": 4, "string": "four"}] ' # 输出: # nine: 9 # four: 4
|
转换 JSON 对象为 key=value 形式
方法 1:
1
| jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" test.json
|
示例:
1 2 3 4 5 6 7 8 9 10 11 12
| $ cat test.json { "var": 1, "foo": "bar", "x": "test" }
$ jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" test.json # 输出: # foo=bar # var=1 # x=test
|
方法 2:
1
| jq -r '.SITE_DATA | to_entries | .[] | .key + "=\"" + .value + "\""' data.json
|
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| $ cat data.json { "SITE_DATA": { "URL": "example.com", "AUTHOR": "John Doe", "CREATED": "10/22/2017" } }
# 输出: # URL="example.com" # AUTHOR="John Doe" # CREATED="10/22/2017"
|
这种格式可以直接使用 eval 命令:
1 2
| eval "$(jq -r '.SITE_DATA | to_entries | .[] | .key + "=\"" + .value + "\""' < data.json)" echo "$AUTHOR"
|
方法 3:循环遍历
1 2 3 4 5 6 7
| constants=$(cat ${1} | jq '.SITE_DATA' | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") for key in ${constants}; do eval ${key} done
echo ${AUTHOR}
|
输出格式控制
将输出压缩为一行
使用 -c 参数:
输出示例:
1 2
| {"key":"SEA-739","status":"Open","assignee":null} {"key":"SEA-738","status":"Resolved","assignee":"user2@mycompany.com"}
|
或者在原命令中使用 -c 替换 -r:
1
| jq -c '(.issues[] | {key, status: .fields.status.name, assignee: .fields.assignee.emailAddress})'
|
数组处理
JSON 数组转 Bash 数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| $ cat json [ { "item1": "value1", "item2": "value2", "sub items": [ { "subitem": "subvalue" } ] }, { "item1": "value1_2", "item2": "value2_2", "sub items_2": [ { "subitem_2": "subvalue_2" } ] } ]
|
代码:
1 2
| arr=( $(jq -r '.[].item2' json) ) printf '%s\n' "${arr[@]}"
|
输出:
遍历 JSON 数组
示例数据:
1 2
| sample='[{"name":"foo"},{"name":"bar"}]' echo "${sample}" | jq '.'
|
使用 jq --compact-output (或 -c) 可以将每个对象输出为一行:
1 2
| sample='[{"name":"foo"},{"name":"bar"}]' echo "${sample}" | jq -c '.[]'
|
输出:
1 2
| {"name":"foo"} {"name":"bar"}
|
如果数据包含空格或换行符,可以使用 base64 编码:
1 2
| sample='[{"name":"foo"},{"name":"bar"}]' echo "${sample}" | jq -r '.[] | @base64'
|
输出:
1 2
| eyJuYW1lIjoiZm9vIn0= eyJuYW1lIjoiYmFyIn0=
|
使用 for 循环遍历:
1 2 3 4 5 6 7
| sample='[{"name":"foo"},{"name":"bar"}]' for row in $(echo "${sample}" | jq -r '.[] | @base64'); do _jq() { echo ${row} | base64 --decode | jq -r ${1} } echo $(_jq '.name') done
|
输出:
实例:
1 2 3 4 5 6 7
| cat test.json | jq -c -r ".[] | {status : .status}" | while read row do _jq() { echo ${row} | jq -r ${1} } echo $(_jq '.status') done
|
以上代码等同于:
1 2 3 4 5 6 7
| cat test.json | jq -r ".[] | {status: .status} | @base64" | while read row do _jq() { echo ${row} | base64 --decode | jq -r ${1} } echo $(_jq '.status') done
|
常见问题
解决报错:parse error: Invalid string: control characters from U+0000 through U+001F must be escaped
这个错误通常是因为 jq 1.5 版本不支持 JSON 中的换行符。解决方法:
1 2 3 4 5
| json_string=$(echo ${string} | tr '\r\n' ' ')
json_string=$(echo ${string} | tr -d '\r\n')
|
通过 tr 函数做替换即可解决问题。