在外壳上进行JSON解析


11

如何解析Shell上的JSON输出?

例如,Amazon Web Services提供了一个CLI来检索实例的状态:

$ aws ec2 describe-instances <my_instance_id>

但是该命令返回JSON字符串。该命令的输出如下所示:

$ aws ec2 describe-instances x12345
{
    "Reservations" :
     {  
            "OwnerId": "1345345"
            "Groups": [], 
            "SecurityGroups": [
               {
                  "Foo" : "yes"
                  "Bar" : "no
               }
             ]
     }
}

是否有可用于解析JSON输出的shell内置程序?

例如,我想在shell变量中捕获FOO以下内容output["Reservations"]["SecurityGroups"][0]{"Foo"}

如果有帮助,我对Zsh可能适用的解决方案特别感兴趣。


2
您通常会使用jshon之类的工具。
jasonwryan 2014年

1
使用--output text,如果你想在shell来解析,而无需使用外部工具,如jshon
jordanm 2014年

1
@jasonwryan- jshon第一次才听说,我关注了您的链接。读完这些之后,我只能说我很高兴我偶然听到并jq首先安装了该软件。我想您可能还想听听它,如果您还没有听说过的话-它不会打扰所有这些命令行开关,并且可以执行自己的正则表达式-甚至允许您根据需要声明函数和变量。如果您有兴趣,请参阅此处的答案。
mikeserv

Answers:


10

据我了解,您正在寻找“ Foo”的价值。这是真的容易与shell命令行工具做jq。就像这样sed,它实现了自己的一种解析器语言。给出您的示例:

json='
{
    "Reservations" :
     {  
            "OwnerId" : "1345345",
            "Groups" :  [],
            "SecurityGroups" : [
               {
                  "Foo" : "yes",
                  "Bar" : "no"
               }
             ]
     }
}'

jq可以yes简单地得到:

printf %s "$json" |
jq '.[].SecurityGroups[0].Foo?'                                                

输出值

"yes"

您可以使用.dot表示法遍历对象散列或字典列表,并且索引数组可以更简单地索引,就像您可能已经猜到的那样,可以使用数字,方括号索引。在上面的命令中,我使用空索引格式表示我希望扩展该级别的所有可迭代项。这样可能更容易理解:

printf %s "$json" | jq '.[][]'

...将散列中第二级项目的所有值分解并让我...

"1345345"
[]
[
  {
    "Foo": "yes",
    "Bar": "no"
  }
]

关于其jq功能,这几乎没有刮擦表面。它是用于在外壳中序列化数据的功能非常强大的工具,它可以以经典的Unix风格编译为单个可执行二进制文件,很可能通过package-manager进行了分发,并且有据可查。请访问其git-page,看看自己。

顺便说一句,处理分层数据的另一种方法json(至少是了解您正在使用的内容)可能是走另一条路,并使用.dot表示法来分解各个级别的所有值,例如:

printf %s "$json" | jq '..'

{
  "Reservations": {
    "OwnerId": "1345345",
    "Groups": [],
    "SecurityGroups": [
      {
        "Foo": "yes",
        "Bar": "no"
      }
    ]
  }
}
{
  "OwnerId": "1345345",
  "Groups": [],
  "SecurityGroups": [
    {
      "Foo": "yes",
      "Bar": "no"
    }
  ]
}
"1345345"
[]
[
  {
    "Foo": "yes",
    "Bar": "no"
  }
]
{
  "Foo": "yes",
  "Bar": "no"
}
"yes"
"no"

但是,更好的方法可能只是使用jq为各种类型的节点提供的众多发现或搜索方法中的一种。


10

这是对您目标的答案,而不是您的问题。这意味着您无需使用JSON解析器就可以实现目标。

AWS cli util能够仅使用--query参数输出选择字段。这在此处记录

例如:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupName' \
  --instance-id i-6b272337 \
  --output text
mongodb

您甚至可以根据需要选择多个字段:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[0].[GroupName,GroupId]' \
  --instance-id i-6b272337 \
  --output text
mongodb sg-710ffa14

您还可以显示多个匹配的结构:

$ aws ec2 describe-instances \
  --query 'Reservations[0].Instances[0].SecurityGroups[*].[GroupName,GroupId]' \
  --instance-id i-6b272337 \
  --output text
mongodb sg-710ffa14
default sg-a0243bcc

1
谢谢!那非常有帮助。我接受@mikeserv主要是为社区提供问题的答案,但是您的答案是我将使用的答案
Amelio Vazquez-Reina 2014年

这非常有帮助!非常感谢你!!
MD塞耶姆·艾哈迈德(Sayem Ahmed)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.