問(wèn)題:shell下使用jq比較兩個(gè)json是否相等教翩,第一個(gè)難點(diǎn)是KEY需要排序秽晚,第二個(gè)難點(diǎn)是array需要排序
Jq 本身提供-S參數(shù)使key進(jìn)行排序
$ jq -c . a
{"array":["fdsfd","12321","g9023ijio"],"zfdsf":"fdsfsd","vfdsadsad":123,"array2":[123,4324,421321],"9fdsfds":123}
$ jq -c -S . a
{"9fdsfds":123,"array":["fdsfd","12321","g9023ijio"],"array2":[123,4324,421321],"vfdsadsad":123,"zfdsf":"fdsfsd"}
不過(guò)無(wú)法處理array.
jq提供了walk功能可以對(duì)所有的key進(jìn)行遍歷,同時(shí)他的example1就展示了如何對(duì)array進(jìn)行排序堵泽,但apt中提供的jq不具有這個(gè)功能修己。
walk(f)
The walk(f) function applies f recursively to every component of the input entity. When an array is encountered, f is first applied to its elements and then to the array itself; when an object is encountered, f is first applied to all the values and then to the object. In practice, f will usually test the type of its input, as illustrated in the following examples. The first example highlights the usefulness of processing the elements of an array of arrays before processing the array itself. The second example shows how all the keys of all the objects within the input can be considered for alteration.
Examples
jq 'walk(if type == "array" then sort else . end)'
?? Input [[4, 1, 7], [8, 5, 2], [3, 6, 9]]
??Output [[1,4,7],[2,5,8],[3,6,9]]
jq 'walk( if type == "object" then with_entries( .? key |= sub( "^_+"; "") ) else . end )'
??Input [ { "_a": { "__b": 2 } } ]
??Output [{"a":{"b":2}}]
在github上找到了可以在jq1.5中使用walk的方法
# Apply f to composite entities recursively, and to atoms
def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;
最后寫(xiě)成了這個(gè)樣子,
#!/bin/bash
# set -x
a=$1
b=$2
a_format=$(echo ${a} |jq 'def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;walk(if type == "array" then sort else . end)')
if [ $? -ne 0 ] ; then
exit 1
fi
b_format=$(echo $迎罗 |jq 'def walk(f):
. as $in
| if type == "object" then
reduce keys[] as $key
( {}; . + { ($key): ($in[$key] | walk(f)) } ) | f
elif type == "array" then map( walk(f) ) | f
else f
end;walk(if type == "array" then sort else . end)')
if [ $? -ne 0 ] ; then
exit 1
fi
a_md5=$(echo ${a_format}|md5sum|cut -f1 -d" ")
b_md5=$(echo ${b_format}|md5sum|cut -f1 -d" ")
if [ "x${a_md5}" = "x${b_md5}" ] ; then
exit 0
fi
exit 1