如何使用Linux命令行工具解析和打印漂亮的JSON

时间:2020-03-21 11:44:47  来源:igfitidea点击:

JSON是一种轻量级且独立于语言的数据存储格式,易于格式化,并且易于与大多数编程语言集成,并且易于理解。
JSON一词代表JavaScript Object Notation,尽管它以JavaScript开头,主要用于在服务器和浏览器之间交换数据,但现在已用于许多领域,包括嵌入式系统。
其中我们将使用Linux上的命令行工具来解析和打印JSON。
这对于在Shell脚本中处理大型JSON数据或者在Shell脚本中处理JSON数据非常有用。

什么是漂亮的打印?

JSON数据的结构使其更具可读性。
但是,在大多数情况下,即使没有行结束符,JSON数据也存储在一行中。

显然,手动阅读和编辑不是很方便。

那时候漂亮的打印很有用。
这个名称很容易解释,重新格式化了JSON文本,使人更易读。
这就是所谓的JSON漂亮打印。

使用Linux命令行工具解析和打印漂亮的JSON

可以使用awk,sed和gerp等命令行文本处理器来解析JSON数据。
实际上,JSON.awk是执行该操作的awk脚本。
但是,有一些专用工具可以达到相同的目的。

  • jq或者jshon,shell的JSON解析器,两者都很有用。
  • Shell脚本(如JSON.sh或者jsonv.sh)可在bash,zsh或者破折号shell中解析JSON。
  • JSON.awk,JSON解析器awk脚本。
  • Python模块,例如json.tool。
  • underscore-cli,Node.js和基于javascript的代码。

在本教程中,我仅关注jq,它是具有强大的JSON解析器的shell,具有高级过滤和脚本编写功能。

JSON漂亮打印

JSON数据对于人类来说可能是一种且几乎难以辨认,因此,为了使其更具可读性,此处使用了JSON漂亮打印。

示例:来自jsonip.com的数据,要获取JSON格式的外部IP地址,请使用curl或者类似以下的wget工具。

$wget -cq http://jsonip.com/-O 

实际数据如下所示:

{"ip":"111.222.333.444","about":"/about","Pro!":"http://getjsonip.com"}

现在用jq漂亮地打印它:

$wget -cq http://jsonip.com/-O - | jq '.'

用jq过滤结果后,结果如下所示。

{
   "ip": "111.222.333.444",
   "about": "/about",
   "Pro!": "http://getjsonip.com"
}

使用python json.tool模块可以完成相同的操作。
这是一个例子:

$cat anything.json | python -m json.tool

这种基于Python的解决方案对于大多数用户来说应该是不错的选择,但是对于未预安装或者无法安装Python的系统(如在嵌入式系统上),它的用处不大。

但是json.tool python模块具有明显的优势,它是跨平台的。
因此,我们可以在Windows,Linux或者Mac OS上无缝使用它。

如何使用jq解析JSON

首先,我们需要安装jq,大多数GNU/Linux发行版已经安装了jq,并使用其各自的软件包安装程序命令进行安装。

在Arch Linux上:

$sudo pacman -S jq

在Debian,Ubuntu和Linux Mint上:

$sudo apt-get install jq

在Fedora上:

$sudo dnf install jq

在openSUSE上:

$sudo zypper install jq

对于其他操作系统或者平台,请参阅官方安装说明。

jq的基本过滤器和标识符

jq可以从stdin或者文件中读取JSON数据。
我们必须根据情况使用两者。

的单一符号。
是最基本的过滤器。
这些过滤器也称为对象标识符索引。
使用单个。
基本上与jq一起打印输入的JSON文件。

单引号我们不必总是使用单引号。
但是,如果要将多个过滤器合并在一行中,则必须使用它们。

双引号必须将任何特殊字符(如@,#,$)括在两个双引号中,例如本例中的jq .foo。
“ @ bar”

原始数据打印无论出于什么原因,如果只需要最终解析的数据(而不用双引号引起来),则可以在jq命令中使用-r标志,如下所示。
jq -r .foo.bar。

解析特定数据

要过滤掉JSON的特定部分,我们必须查看漂亮打印的JSON文件的数据层次结构。

来自Wikipedia的JSON数据示例:

{
  "firstName": "John",
  "lastName": "Smith",
  "age": 25,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10021"
},
  "phoneNumber": [
{
  "type": "home",
  "number": "212 555-1234"
},
{
  "type": "fax",
  "number": "646 555-4567"
}
],
  "gender": {
  "type": "male"
  }
}

在本教程中,我将使用此JSON数据作为示例,并将其另存为sample.json。

假设我要从sample.json文件中过滤出地址。
所以命令应该像这样:

$jq .address sample.json

输出示例:

{
  "streetAddress": "21 2nd Street",
  "city": "New York",
  "state": "NY",
  "postalCode": "10021"
}

再说一遍,我想要邮政编码,然后添加另一个对象标识符索引,例如:另一个过滤器。

$cat sample.json | jq .address.postalCode

还要注意,过滤器区分大小写,我们必须使用完全相同的字符串来获取有意义的输出,而不是null。

解析JSON数组中的元素

JSON数组的元素括在方括号内,无疑使用起来非常灵活。

要解析数组中的元素,必须使用[] identifier以及其他对象的identifier-index。

在此示例JSON数据中,电话号码存储在一个数组中,要从该数组中获取所有内容,我们仅需使用方括号,如本例所示。

$jq .phoneNumber[] sample.json

假设我们只需要数组的第一个元素,然后使用从0开始的数组对象编号,对于第一个项目,使用[0],对于下一个项目,它应该每步增加一个。

$jq .phoneNumber[0] sample.json

脚本示例

假设我只想要家庭的电话号码,而不是整个JSON数组数据。
这是使用jq命令中的脚本方便的时候。

$cat sample.json | jq -r '.phoneNumber[] | select(.type == "home") | .number'

其中我首先将一个文件管理器的结果传递给另一个,然后使用select属性选择一种特定类型的数据,再将结果传递给另一个过滤器。