json 简介
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它使得人们很容易进行阅读和编写。同时也方便了机器进行解析和生成。它是基于 JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON采用完全独立于程序语言的文本格式,但是也使用了类C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性决定了 JSON 格式越来越广泛的应用于现代的各种系统中。作为系统管理员,在日常的工作中无论是编辑配置文件或者通过 http 请求查询信息,我们都不可避免的要处理 JSON 格式的数据。
JSON 数据的书写格式是: 名称:对象。
JSON的结构基于两点
“名称/值”的集合:在不同的语言中,它可以被理解为对象(object),记录(record),结构(struct),字典(dictionary),哈希表(hash table),键列表(keyed list)等 .
值的有序列表:多数语言中被理解为数组(array)
JSON的基础结构说明
对象是属性、值的集合。一个对象开始与”{” ,结束于”}”。每一个属性名和值间用”:”分隔。每个属性间用”,”分隔。
值可以是字符串,数字,逻辑值,数组,对象,null。
数值:十进制数,不能有前导0,可以为负数,可以有小数部分。还可以用
e
或者E
表示指数部分。不能包含非数,如NaN。不区分整数与浮点数。JavaScript用双精度浮点数表示所有数值。字符串:以双引号
""
括起来的零个或多个Unicode码位。支持反斜杠开始的转义字符序列。布尔值:表示为
true
或者false
。值的有序列表(array):有序的零个或者多个值。每个值可以为任意类型。序列表使用方括号
[
,]
括起来。元素之间用逗号,
分割。形如:[value, value]
对象(object):一个无序的“键-值对”(pair),其中键是字符串。建议但不强制要求对象中的键是独一无二的。对象以花括号
{
开始,并以}
结束。键-值对之间使用逗号分隔。键与值之间用冒号:
分割。null类型:值写为
null
◎JSON维基百科 | Wiki:json
jq 简介
jq 是一款命令行下处理 JSON 数据的工具。其可以接受标准输入,命令管道或者文件中的 JSON 数据,经过一系列的过滤器(filters)和表达式的转换后形成我们需要的数据结构并将结果输出到标准输出中。jq 的这种特性使我们可以很容易地在 Shell 脚本中调用它。
jq可以对json数据进行分片、过滤、映射和转换,和sed、awk、grep等命令一样,都可以让你轻松地把玩文本。它能轻松地把你拥有的数据转换成你期望的格式,而且需要写的程序通常也比你期望的更加简短。
jq是用C编写,没有运行时依赖,所以几乎可以运行在任何系统上。预编译的二进制文件可以直接在Linux、OS X和windows系统上运行,当然在linux和OS X系统你需要赋与其可执行权限;在linux系统中也可以直接用yum安装。
jq 安装
下载安装:https://stedolan.github.io/jq/download/
MacOS
brew install jq
Ubuntu
sudo apt install jq -y
CentOS
rpm -ivh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm sudo yum repolist yum install jq -y
二进制安装
wget http://stedolan.github.io/jq/download/linux64/jq chmod +x ./jq sudo cp jq /usr/bin
源码安装
git clone https://github.com/stedolan/jq.git cd jq autoreconf -i ./configure --disable-maintainer-mode make sudo make install
jq 常用方法
官网使用手册:jq Manual
jq在线过滤器:jq play
使用
man jq
创建
[root@test-dhcp ~]# jq -n {a:1} { "a": 1 } [root@test-dhcp ~]# jq -n '{a:"test"}' { "a": "test" }
合并
[root@test-dhcp ~]# jq -n '{a:"test"} + {b:2}' { "a": "test", "b": 2 } [root@test-dhcp ~]# jq -n '{a:"test"} + {b:2} + {c:"testc"}' { "a": "test", "b": 2, "c": "testc" }
删除
[root@test-dhcp ~]# cat test.json {"a": "test","b": 2, "c": "testc"} [root@test-dhcp ~]# cat test.json |jq . { "a": "test", "b": 2, "c": "testc" } [root@test-dhcp ~]# cat test.json |jq 'del(.b)' { "a": "test", "c": "testc" }
更新
[root@test-dhcp ~]# cat test.json {"a": "test","b": 2, "c": "testc"} [root@test-dhcp ~]# cat test.json |jq '.b="testb"' { "a": "test", "b": "testb", "c": "testc" } [root@test-dhcp ~]# cat test.json |jq '. + {d:4}' { "a": "test", "b": 2, "c": "testc", "d": 4 } [root@test-dhcp ~]# cat test.json |jq '. + {d:4}' |jq '.d={dd:5}' { "a": "test", "b": 2, "c": "testc", "d": { "dd": 5 } }
查询
[root@test-dhcp ~]# cat test.json |jq . { "a": "test", "b": 2, "c": "testc", "d": { "dd": 5 } } [root@test-dhcp ~]# cat test.json |jq '. + {d:4}' |jq '.d={dd:5}' |jq .d.dd 5 [root@test-dhcp ~]# echo '{"a":1,"b":2}' |jq '[.a,.b]' [ 1, 2 ]
查看数据类型
[root@test-dhcp ~]# echo "{}" |jq -r type object [root@test-dhcp ~]# echo '[0, false, [], {}, null, "hello"]' |jq 'map(type)' [ "number", "boolean", "array", "object", "null", "string" ]
查询数组中的值
[root@test-dhcp ~]# echo [1,2,3] |jq .[1] 2 [root@test-dhcp ~]# echo [1,2,3] |jq .[2] 3
查询数组长度
[root@test-dhcp ~]# echo [1,2,3,9] |jq '.|length' 4 [root@test-dhcp ~]# echo [1,2,3] |jq '.|length' 3
数组相加
[root@test-dhcp ~]# echo [1,2,3] |jq '. + [4,5,6]' [ 1, 2, 3, 4, 5, 6 ]
高级查询
[root@test-dhcp ~]# echo [1,2,3] | jq 'map(select(. >= 2))' [ 2, 3 ] [root@test-dhcp ~]# echo [1,2,3] | jq 'map(select(. == 2))' [ 2 ] [root@test-dhcp ~]# echo [1,2,3] | jq 'map(select(. != 2))' [ 1, 3 ] [root@test-dhcp ~]# cat test.json [ { "id": "0", "model": "Intel(R)Xeon(R)CPUE5-2620v4@2.10GHz" }, { "id": "1", "model": "Intel(R)Xeon(R)CPUE5-2620v4@2.10GHz" } ] [root@test-dhcp ~]# cat test.json |jq .[].model "Intel(R)Xeon(R)CPUE5-2620v4@2.10GHz" "Intel(R)Xeon(R)CPUE5-2620v4@2.10GHz"
类型转换
[root@test-dhcp ~]# echo '["a","b,c,d","e"]' |jq 'join(",")' "a,b,c,d,e" [root@test-dhcp ~]# echo '["a","b,c,d","e",1]' |jq 'join(",")' jq: error (at <stdin>:1): string (",") and number (1) cannot be added [root@test-dhcp ~]# cat test.json liuxin,30,male jiaweiqiang,29,femal [root@test-dhcp ~]# jq -R 'split(",")|{"name":.[0],"age":.[1],"sex":.[2]}' ./test.json { "name": "liuxin", "age": "30", "sex": "male" } { "name": "jiaweiqiang", "age": "29", "sex": "femal" } [root@test-dhcp ~]# cat test.json { "name": "liuxin", "age": "30", "sex": "male" } { "name": "jiaweiqiang", "age": "29", "sex": "femal" } [root@test-dhcp ~]# cat test.json |jq . -c {"name":"liuxin","age":"30","sex":"male"} {"name":"jiaweiqiang","age":"29","sex":"femal"}
过滤service节点name
[ { "id": 508886, "name": "chegva.com", "desc_name": "website", "deps": "", "category": "service", "comment": "", "serviceLevel": "3", "owners": "[]", "sreOwners": "[]", "type": "parent", "su": "", "usn": "chegva_com", "budgetTags": "", "region": "大陆", "is_collect": "否", "extra": "", "tmpextra": { "String": "", "Valid": true } ] 执行:jq -r 'map(select(.category=="service")) | .[].name' 结果:chegva.com 查询多个值:jq -r '[].name,[].usn' 逻辑运算符:jq -r 'map(select(.name=="chegva.com" and .serviceLevel==3))' { "worksheet_detail": { .... "message_list": [ { "id": "7084124066314977389", "message_id": "7084124007615692909", "message_type": "text", "created_at": 1649401152000, "content": "{\"++++++++++++++++\",\"msg_type\":\"text\"}", "user_name": "anzhihe", "user_id": "0" }, { "id": "7084124066331803757", "message_id": "7084124009872244845", "message_type": "text", "created_at": 1649401152000, "content": "{\"content\":\"-----------------\",\"msg_type\":\"text\"}", "user_name": "bot", "user_id": "0" }, ... ] } } 多重查询:jq -r '.data|.["worksheet_detail"]["message_list"]|map(select(.user_name!="bot"))|.[0,1,2,3]|{user_name,content}'
jq从数组中删除空字符串
Attempt: echo '["bob","","tim",""]' | jq '[ . [] | if length > 0 then . end ]' Desired output: ["bob", "tim"] Error: . [] | if length > 0 then . end jq: error: Possibly unterminated 'if' statement at <top-level>, line 1: . [] | if length > 0 then . end jq: 2 compile errors Answer: Adding "else empty" gets the right result jq '[ .[] | if length > 0 then . else empty end ]' Consider using select instead. jq '[ .[] | select(length > 0) ]' And since map(x) is equivalent to [.[] | x], we can do this. jq 'map(select(length > 0))'
参考: