json文件解析神器jq使用

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官网


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

  1. 使用

man jq
  1. 创建

[root@test-dhcp ~]# jq -n {a:1}
{
  "a": 1
}
[root@test-dhcp ~]# jq -n '{a:"test"}'
{
  "a": "test"
}
  1. 合并

[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"
}
  1. 删除

[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"
}
  1. 更新

[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
  }
}
  1. 查询

[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
]
  1. 查看数据类型

[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"
]
  1. 查询数组中的值

[root@test-dhcp ~]# echo [1,2,3] |jq .[1]
2
[root@test-dhcp ~]# echo [1,2,3] |jq .[2]
3
  1. 查询数组长度

[root@test-dhcp ~]# echo [1,2,3,9] |jq '.|length'
4
[root@test-dhcp ~]# echo [1,2,3] |jq '.|length'
3
  1. 数组相加

[root@test-dhcp ~]# echo [1,2,3] |jq '. + [4,5,6]'
[
  1,
  2,
  3,
  4,
  5,
  6
]
  1. 高级查询

[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"
  1. 类型转换

[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"}
  1. 过滤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}'
  1. 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))'


参考:

anzhihe 安志合个人博客,版权所有 丨 如未注明,均为原创 丨 转载请注明转自:https://chegva.com/3659.html | ☆★★每天进步一点点,加油!★★☆ | 

您可能还感兴趣的文章!

发表评论

电子邮件地址不会被公开。 必填项已用*标注