JSON是前端编程经常用到的格式,对于PHP或者Python,解析JSON都不是什么大事,尤其是PHP的json_encode和json_decode,干的相当的漂亮。Linux下也有处理处理JSON的神器:jq。 对于JSON格式而言,jq就像sed/awk/grep这些神器一样的方便,而也,jq没有乱七八糟的依赖,只需要一个binary文件jq,就足矣。下面我们看下jq的使用。 1. 安装 官网:https://stedolan.github.io/jq/download/ Linux jq 1.5…
Shell:jq 循环 json 对象, jq 循环 json 数组, jq 用法实践, jq converts a JSON object to key=value, jq parses one field from an JSON array into bash array
1. 转换数字为字符串 How do I use jq to convert number to string?
Given the following jq command and Json:
jq '.[]|[.string,.number]|join(": ")' <<< ' [ { "number": 3, "string": "threee" }, { "number": 7, "string": "seven" } ] '
I’m trying to format the output as:
three: 3 seven: 7
方法:The jq command has the tostring function. It took me a while to learn to use it by trial and error. Here is how to use it:
jq -r '.[] | [ .string, .number|tostring ] | join(": ")' <<< ' [{ "number": 9, "string": "nine"}, { "number": 4, "string": "four"}] ' #nine: 9 #four: 4
2. 转换 json 对象为 key=value 形式,How to convert a JSON object to key=value format in jq?
In jq, how can I convert a JSON to a string with key=value
?
From:
{ "var": 1, "foo": "bar", "x": "test" }
To:
var=1 foo=bar x=test
方法:You could try:
jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" test.json
Here’s a demo:
$ 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
或者可以使用:
$ cat data.json { "SITE_DATA": { "URL": "example.com", "AUTHOR": "John Doe", "CREATED": "10/22/2017" } }
You can make a much simpler version of the jq program:
jq -r '.SITE_DATA | to_entries | .[] | .key + "=\"" + .value + "\""'
which outputs:
URL="example.com" AUTHOR="John Doe" CREATED="10/22/2017"
This string is eval
able as long as the characters `
, $
, newline and null don’t appear in the data:
eval "$(jq -r '.SITE_DATA | to_entries | .[] | .key + "=\"" + .value + "\""' < data.json)" echo "$AUTHOR"
或者:
Just realized that I can loop over the results and eval each iteration:
constants=$(cat ${1} | jq '.SITE_DATA' | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]") for key in ${constants}; do eval ${key} done
Allows me to do:
echo ${AUTHOR} # outputs John Doe
3. 将输出化为一行 Get outputs from jq on a single line
-c
is what you likely need
Using the output you posted above, you can process it further:
jq -c . input
To Give;
{"key":"SEA-739","status":"Open","assignee":null} {"key":"SEA-738","status":"Resolved","assignee":"user2@mycompany.com"}
Or you can just change your original command
FROM
jq -r '(.issues[] | {key, status: .fields.status.name, assignee: .fields.assignee.emailAddress})'
TO
jq -c '(.issues[] | {key, status: .fields.status.name, assignee: .fields.assignee.emailAddress})'
4. json 数组转 bash 数组 parse one field from an JSON array into bash array
I have a JSON output that contains a list of objects stored in a variable. (I may not be phrasing that right)
[ { "item1": "value1", "item2": "value2", "sub items": [ { "subitem": "subvalue" } ] }, { "item1": "value1_2", "item2": "value2_2", "sub items_2": [ { "subitem_2": "subvalue_2" } ] } ]
Using jq :
$ cat json [ { "item1": "value1", "item2": "value2", "sub items": [ { "subitem": "subvalue" } ] }, { "item1": "value1_2", "item2": "value2_2", "sub items_2": [ { "subitem_2": "subvalue_2" } ] } ]
CODE:
arr=( $(jq -r '.[].item2' json) ) printf '%s\n' "${arr[@]}"
OUTPUT:
value2 value2_2
5. jq 遍历 json 数组,遍历 json 对象,Bash for Loop Over JSON Array Using jq
First we will start with some data:
sample='[{"name":"foo"},{"name":"bar"}]' echo "${sample}" | jq '.'
输出
[ { "name": "foo" }, { "name": "bar" } ]
By using jq --compact-output
(or -c
) we can get each object on a newline.
sample='[{"name":"foo"},{"name":"bar"}]' echo "${sample}" | jq -c '.[]'
输出
{"name":"foo"} {"name":"bar"}
We could start iterating of the above with a Bash for loop if our data does not contain spaces or newlines. But since certificates contain newlines we better base64 encode each line. Also, instead of -c
, we now use -r
to get rid of the extra quotes.
sample='[{"name":"foo"},{"name":"bar"}]' echo "${sample}" | jq -r '.[] | @base64'
输出
eyJuYW1lIjoiZm9vIn0= eyJuYW1lIjoiYmFyIn0=
Now let’s build our for loop.
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
输出
foo bar
实例:
cat test.json | jq -c -r ".[] | {status : .status}" | while read row do _jq() { echo ${row} | jq -r ${1} } echo $(_jq '.status') done
以上代码等同于:
cat test.json | jq -r ".[] | {status: .status} | @base64" | while read row do _jq() { echo ${row} | base64 --decode | jq -r ${1} } echo $(_jq '.status') done
6. 解决报错:parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 3, column 9 或者 jq: error (at :1): Cannot index string with string “expand”
Newlines not supported on jqplay with jq 1.5. They must be escaped as \n or as \u000a.
一般原因是因为 jq 1.5的版本不知道 json 换行,解决方法如下:
json_string=$(echo ${string} | tr '\r\n' ' ') #或者采用直接删除的方式 json_string=$(echo ${string} | tr -d '\r\n')
通过 tr 函数做一个替换即可!
7. jq 在线测试网站:
在线测试:https://jqplay.org/
手册:https://stedolan.github.io/jq/manual/