如何在Linux上使用Shell脚本解析JSON?

8

我需要在linux中从一个Json输出中提取几个参数。

这是Json输出:

{
  "OwnerId":"121456789127",
  "ReservationId":"r-48465168",
  "Groups":[

  ],
  "Instances":[
    {
      "Monitoring":{
        "State":"disabled"
      },
      "PublicDnsName":null,
      "RootDeviceType":"ebs",
      "State":{
        "Code":16,
        "Name":"running"
      },
      "EbsOptimized":false,
      "LaunchTime":"2014-03-19T09:16:56.000Z",
      "PrivateIpAddress":"10.250.171.248",
      "ProductCodes":[
        {
          "ProductCodeId":"aacglxeowvn5hy8sznltowyqe",
          "ProductCodeType":"marketplace"
        }
      ],
      "VpcId":"vpc-86bab0e4",
      "StateTransitionReason":null,
      "InstanceId":"i-1234576",
      "ImageId":"ami-b7f6c5de",
      "PrivateDnsName":"ip-10-120-134-248.ec2.internal",
      "KeyName":"Test_Virginia",
      "SecurityGroups":[
        {
          "GroupName":"Test",
          "GroupId":"sg-12345b"
        }
      ],
      "ClientToken":"VYeFw1395220615808",
      "SubnetId":"subnet-12345314",
      "InstanceType":"t1.micro",
      "NetworkInterfaces":[
        {
          "Status":"in-use",
          "SourceDestCheck":true,
          "VpcId":"vpc-123456e4",
          "Description":"Primary network interface",
          "NetworkInterfaceId":"eni-3619f31d",
          "PrivateIpAddresses":[
            {
              "Primary":true,
              "PrivateIpAddress":"10.120.134.248"
            }
          ],
          "Attachment":{
            "Status":"attached",
            "DeviceIndex":0,
            "DeleteOnTermination":true,
            "AttachmentId":"eni-attach-9210dee8",
            "AttachTime":"2014-03-19T09:16:56.000Z"
          },
          "Groups":[
            {
              "GroupName":"Test",
              "GroupId":"sg-123456cb"
            }
          ],
          "SubnetId":"subnet-31236514",
          "OwnerId":"109030037527",
          "PrivateIpAddress":"10.120.134.248"
        }
      ],
      "SourceDestCheck":true,
      "Placement":{
        "Tenancy":"default",
        "GroupName":null,
        "AvailabilityZone":"us-east-1c"
      },
      "Hypervisor":"xen",
      "BlockDeviceMappings":[
        {
          "DeviceName":"/dev/sda",
          "Ebs":{
            "Status":"attached",
            "DeleteOnTermination":false,
            "VolumeId":"vol-37ff097b",
            "AttachTime":"2014-03-19T09:17:00.000Z"
          }
        }
      ],
      "Architecture":"x86_64",
      "KernelId":"aki-88aa75e1",
      "RootDeviceName":"/dev/sda1",
      "VirtualizationType":"paravirtual",
      "Tags":[
        {
          "Value":"Server for testing RDS feature in us-east-1c AZ",
          "Key":"Description"
        },
        {
          "Value":"RDS_Machine (us-east-1c)",
          "Key":"Name"
        },
          {
          "Value":"1234",
          "Key":"Cost.centre"
        },
        {
          "Value":"Jyoti Bhanot",
          "Key":"Owner"
        }
      ],
      "AmiLaunchIndex":0
    }
  ]
}

期望输出:

 Instance id         Name                           cost centre             Owner
    i-1234576          RDS_Machine (us-east-1c)        1234                   Jyoti Bhanot

我想写一个包含实例ID、名称标签、成本中心和所有者等标题的文件,下面是从JSON输出中提取的某些值。这里给出的输出只是一个示例。
请问如何使用sed和awk实现?
感谢任何帮助。
谢谢。

你能提供一下你对上面示例的期望输出吗? - anubhava
还不对。value 1.1 在您期望的输出中,但不在 JSON 中。 - anubhava
好的,现在看起来更好了,让我尝试使用 jq - anubhava
1
你忘记在 "Cost.center" } 后面加上 , 了。 - Muhammad Baja Aksha
可以实现,但还没有想出来。 - anubhava
显示剩余6条评论
2个回答

14

以下是使用 jsawk 的示例。 参考:使用Unix工具解析JSON

设置:

首先从https://github.com/micha/jsawk下载jsawk

$ curl -L http://github.com/micha/jsawk/raw/master/jsawk > jsawk
$ chmod 755 jsawk && mv jsawk ~/bin/

在您使用jsawk之前,您可能需要先安装js-devel。 我使用的是Fedora,所以我做的是:

$ sudo yum install js-devel

测试内容:

我将您提供的JSON输出样本复制到文本文件中,命名为sample.json。这里是一个从您的JSON输出样本中获取值的示例:

$ jsawk 'return this.Instances[0].Monitoring.State' < sample.json
disabled
$ jsawk 'return this.Instances[0].VpcId' < sample.json
vpc-86bab0e4

对于来自URL的JSON数据,您可以使用curl http://someserver.com/data.json代替cat
$ curl http://someserver.com/data.json | jsawk 'return this.Instances[0].VpcId'
vpc-86bab0e4

你可以在你的bash文件中使用这些命令来生成包含所需字符串/文本的新文件。你可以从我提供的GitHub链接中了解更多关于jsawk的信息。
这是你需要的内容吗?

看起来这是一个重复的问题:https://dev59.com/bX3aa4cB1Zd3GeqPdXRy?lq=1 和 https://dev59.com/3HI-5IYBdhLWcg3wO1vl - Muhammad Baja Aksha
2
正如Rahul R Dhobi所说,你可能想看看这个链接:https://dev59.com/3HI-5IYBdhLWcg3wO1vl,以解决你的具体问题。[jsawk](https://github.com/micha/jsawk)可能是你的答案。 - Muhammad Baja Aksha
请查看我的修改后的答案。我无法为您编写生成所需文件的shell脚本,但您应该从这里了解如何自己编写它。如果可以的话,请告诉我它是否有效。 - Muhammad Baja Aksha
1
你可以编写一个脚本,为这100多个服务器中的每一个调用它。 - icedwater
请参考这篇文章:**使用bash shell编写脚本的快速指南**,了解如何编写shell脚本。首先自己尝试一下,如果需要帮助,请再次提问或搜索。 - Muhammad Baja Aksha

0

纯 Bash 3.2+,无需依赖(如 jq,python,grep 等):

source <(curl -s -L -o- https://github.com/lirik90/bashJsonParser/raw/master/jsonParser.sh)
read -d '' JSON << EOF
// put your json here
EOF
JSON=$(minifyJson "$JSON")
id=$(parseJson "$JSON" Instances 0 InstanceId)
name=$(parseJson "$JSON" Instances 0 Tags 1 Value)
cost=$(parseJson "$JSON" Instances 0 Tags 2 Value)
owner=$(parseJson "$JSON" Instances 0 Tags 3 Value)
echo -e "Instance id |\t\t Name \t\t\t\t| cost centre | Owner"
echo -e "$id \t| $name  | $cost\t\t  | $owner"

输出:

Instance id |        Name               | cost centre | Owner
i-1234576   | RDS_Machine (us-east-1c)  | 1234        | Jyoti Bhanot

试一下吧


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接