如何使用 jq 将 JSON 字符串格式化为表格?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39139107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:34:59  来源:igfitidea点击:

How to format a JSON string as a table using jq?

jsonbashjq

提问by Rein

Just started out with Bash scripting and stumbled upon jq to work with JSON.

刚开始使用 Bash 脚本编写并偶然发现 jq 可以使用 JSON。

I need to transform a JSON string like below to a table for output in the terminal.

我需要将如下所示的 JSON 字符串转换为表格以在终端中输出。

[{
    "name": "George",
    "id": 12,
    "email": "[email protected]"
}, {
    "name": "Hyman",
    "id": 18,
    "email": "[email protected]"
}, {
    "name": "Joe",
    "id": 19,
    "email": "[email protected]"
}]

What I want to display in the terminal:

我想在终端中显示的内容:

ID        Name
=================
12        George
18        Hyman
19        Joe

Notice how I don't want to display the email property for each row, so the jq command should involve some filtering. The following gives me a plain list of names and id's:

注意我不想显示每一行的 email 属性,所以 jq 命令应该涉及一些过滤。以下为我提供了一个简单的名称和 ID 列表:

list=$(echo "$data" | jq -r '.[] | .name, .id')
printf "$list"

The problem with that is, I cannot display it like a table. I know jq has some formatting options, but not nearly as good as the options I have when using printf. I think I want to get these values in an array which I can then loop through myself to do the formatting...? The things I tried give me varying results, but never what I really want.

问题是,我不能像表格一样显示它。我知道 jq 有一些格式选项,但不如我使用printf. 我想我想在一个数组中获取这些值,然后我可以循环自己来进行格式化......?我尝试的事情给了我不同的结果,但从来没有我真正想要的。

Can someone point me in the right direction?

有人可以指出我正确的方向吗?

采纳答案by sjsam

Why not something like :

为什么不是这样的:

echo '[{
    "name": "George",
    "id": 12,
    "email": "[email protected]"
}, {
    "name": "Hyman",
    "id": 18,
    "email": "[email protected]"
}, {
    "name": "Joe",
    "id": 19,
    "email": "[email protected]"
}]' | jq -r '.[] | "\(.id)\t\(.name)"'

Output

输出

12  George
18  Hyman
19  Joe


Edit 1 :For fine grained formatting use tools like awk

编辑 1:对于细粒度格式,请使用类似的工具awk

 echo '[{
    "name": "George",
    "id": 12,
    "email": "[email protected]"
}, {
    "name": "Hyman",
    "id": 18,
    "email": "[email protected]"
}, {
    "name": "Joe",
    "id": 19,
    "email": "[email protected]"
}]' | jq -r '.[] | [.id, .name] | @csv' | awk -v FS="," 'BEGIN{print "ID\tName";print "============"}{printf "%s\t%s%s",,,ORS}'
ID  Name
============
12  "George"
18  "Hyman"
19  "Joe"


Edit 2 :In reply to

编辑2:回复

There's no way I can get a variable containing an array straight from jq?

我无法直接从 jq 获取包含数组的变量?

Why not?

为什么不?

A bit involved example( in fact modified from yours ) where email is changed to an array demonstrates this

一个有点涉及的例子(实际上是从你的修改而来的),其中电子邮件被更改为数组演示了这一点

echo '[{
    "name": "George",
    "id": 20,
    "email": [ "[email protected]" , "[email protected]" ]
}, {
    "name": "Hyman",
    "id": 18,
    "email": [ "[email protected]" , "[email protected]" ]
}, {
    "name": "Joe",
    "id": 19,
    "email": [ "[email protected]" ]
}]' | jq -r '.[] | .email'

Output

输出

[
  "[email protected]",
  "[email protected]"
]
[
  "[email protected]",
  "[email protected]"
]
[
  "[email protected]"
]

回答by peak

Using the @tsvfilter has much to recommend it, mainly because it handles numerous "edge cases" in a standard way:

使用@tsv过滤器有很多值得推荐的地方,主要是因为它以标准方式处理许多“边缘情况”:

.[] | [.id, .name] | @tsv

Adding the headers can be done like so:

添加标题可以这样完成:

jq -r '["ID","NAME"], ["--","------"], (.[] | [.id, .name]) | @tsv'

The result:

结果:

ID  NAME
--  ------
12  George
18  Hyman
19  Joe

length*"-"

length*"-"

To automate the production of the line of dashes:

要自动生成虚线:

jq -r '(["ID","NAME"] | (., map(length*"-"))), (.[] | [.id, .name]) | @tsv'

回答by Ярослав Рахматуллин

Defining headers by hand is suboptimal! Omitting headers is also suboptimal.

手动定义标题是次优的!省略标题也是次优的。

TL;DR

TL; 博士

data

数据

[{ "name": "George", "id": 12, "email": "[email protected]" },
{ "name": "Hyman", "id": 18, "email": "[email protected]" }, 
{ "name": "Joe", "id": 19, "email": "[email protected]" }]

script

脚本

  [.[]| with_entries( .key |= ascii_downcase ) ]
      |    (.[0] |keys_unsorted | @tsv)
         , (.[]|.|map(.) |@tsv)

how to run

怎么跑

$ < data jq -rf script  | column -t
name    id  email
George  12  [email protected]
Hyman    18  [email protected]
Joe     19  [email protected]

I found this question while summarizng some data from amazon web services. The problem I was working on, in case you want another example:

我在总结来自亚马逊网络服务的一些数据时发现了这个问题。我正在解决的问题,如果你想要另一个例子:

$ aws ec2 describe-spot-instance-requests | tee /tmp/ins |
    jq  --raw-output '
                                     # extract instances as a flat list.
    [.SpotInstanceRequests | .[] 
                                     # remove unwanted data
    | { 
        State, 
        statusCode: .Status.Code, 
        type: .LaunchSpecification.InstanceType, 
        blockPrice: .ActualBlockHourlyPrice, 
        created: .CreateTime, 
        SpotInstanceRequestId}
    ] 
                                        # lowercase keys
                                        # (for predictable sorting, optional)
    |  [.[]| with_entries( .key |= ascii_downcase ) ]
        |    (.[0] |keys_unsorted | @tsv)               # print headers
           , (.[]|.|map(.) |@tsv)                       # print table
    ' | column -t

Output:

输出:

state      statuscode                   type     blockprice  created                   spotinstancerequestid
closed     instance-terminated-by-user  t3.nano  0.002000    2019-02-24T15:21:36.000Z  sir-r5bh7skq
cancelled  bad-parameters               t3.nano  0.002000    2019-02-24T14:51:47.000Z  sir-1k9s5h3m
closed     instance-terminated-by-user  t3.nano  0.002000    2019-02-24T14:55:26.000Z  sir-43x16b6n
cancelled  bad-parameters               t3.nano  0.002000    2019-02-24T14:29:23.000Z  sir-2jsh5brn
active     fulfilled                    t3.nano  0.002000    2019-02-24T15:37:26.000Z  sir-z1e9591m
cancelled  bad-parameters               t3.nano  0.002000    2019-02-24T14:33:42.000Z  sir-n7c15y5p

Input:

输入:

$ cat /tmp/ins
{
    "SpotInstanceRequests": [
        {
            "Status": {
                "Message": "2019-02-24T15:29:38+0000 : 2019-02-24T15:29:38+0000 : Spot Instance terminated due to user-initiated termination.", 
                "Code": "instance-terminated-by-user", 
                "UpdateTime": "2019-02-24T15:31:03.000Z"
            }, 
            "ActualBlockHourlyPrice": "0.002000", 
            "ValidUntil": "2019-03-03T15:21:36.000Z", 
            "InstanceInterruptionBehavior": "terminate", 
            "Tags": [], 
            "InstanceId": "i-0414083bef5e91d94", 
            "BlockDurationMinutes": 60, 
            "SpotInstanceRequestId": "sir-r5bh7skq", 
            "State": "closed", 
            "ProductDescription": "Linux/UNIX", 
            "LaunchedAvailabilityZone": "eu-north-1a", 
            "LaunchSpecification": {
                "Placement": {
                    "Tenancy": "default", 
                    "AvailabilityZone": "eu-north-1a"
                }, 
                "ImageId": "ami-6d27a913", 
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda1", 
                        "VirtualName": "root", 
                        "NoDevice": "", 
                        "Ebs": {
                            "Encrypted": false, 
                            "DeleteOnTermination": true, 
                            "VolumeType": "gp2", 
                            "VolumeSize": 8
                        }
                    }
                ], 
                "EbsOptimized": false, 
                "SecurityGroups": [
                    {
                        "GroupName": "default"
                    }
                ], 
                "Monitoring": {
                    "Enabled": false
                }, 
                "InstanceType": "t3.nano", 
                "AddressingType": "public", 
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0, 
                        "Description": "eth-zero", 
                        "NetworkInterfaceId": "", 
                        "DeleteOnTermination": true, 
                        "SubnetId": "subnet-420ffc2b", 
                        "AssociatePublicIpAddress": true
                    }
                ]
            }, 
            "Type": "one-time", 
            "CreateTime": "2019-02-24T15:21:36.000Z", 
            "SpotPrice": "0.008000"
        }, 
        {
            "Status": {
                "Message": "Your Spot request failed due to bad parameters.", 
                "Code": "bad-parameters", 
                "UpdateTime": "2019-02-24T14:51:48.000Z"
            }, 
            "ActualBlockHourlyPrice": "0.002000", 
            "ValidUntil": "2019-03-03T14:51:47.000Z", 
            "InstanceInterruptionBehavior": "terminate", 
            "Tags": [], 
            "Fault": {
                "Message": "Invalid device name /dev/sda", 
                "Code": "InvalidBlockDeviceMapping"
            }, 
            "BlockDurationMinutes": 60, 
            "SpotInstanceRequestId": "sir-1k9s5h3m", 
            "State": "cancelled", 
            "ProductDescription": "Linux/UNIX", 
            "LaunchedAvailabilityZone": "eu-north-1a", 
            "LaunchSpecification": {
                "Placement": {
                    "Tenancy": "default", 
                    "AvailabilityZone": "eu-north-1a"
                }, 
                "ImageId": "ami-6d27a913", 
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda", 
                        "VirtualName": "root", 
                        "NoDevice": "", 
                        "Ebs": {
                            "Encrypted": false, 
                            "DeleteOnTermination": true, 
                            "VolumeType": "gp2", 
                            "VolumeSize": 8
                        }
                    }
                ], 
                "EbsOptimized": false, 
                "SecurityGroups": [
                    {
                        "GroupName": "default"
                    }
                ], 
                "Monitoring": {
                    "Enabled": false
                }, 
                "InstanceType": "t3.nano", 
                "AddressingType": "public", 
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0, 
                        "Description": "eth-zero", 
                        "NetworkInterfaceId": "", 
                        "DeleteOnTermination": true, 
                        "SubnetId": "subnet-420ffc2b", 
                        "AssociatePublicIpAddress": true
                    }
                ]
            }, 
            "Type": "one-time", 
            "CreateTime": "2019-02-24T14:51:47.000Z", 
            "SpotPrice": "0.011600"
        }, 
        {
            "Status": {
                "Message": "2019-02-24T15:02:17+0000 : 2019-02-24T15:02:17+0000 : Spot Instance terminated due to user-initiated termination.", 
                "Code": "instance-terminated-by-user", 
                "UpdateTime": "2019-02-24T15:03:34.000Z"
            }, 
            "ActualBlockHourlyPrice": "0.002000", 
            "ValidUntil": "2019-03-03T14:55:26.000Z", 
            "InstanceInterruptionBehavior": "terminate", 
            "Tags": [], 
            "InstanceId": "i-010442ac3cc85ec08", 
            "BlockDurationMinutes": 60, 
            "SpotInstanceRequestId": "sir-43x16b6n", 
            "State": "closed", 
            "ProductDescription": "Linux/UNIX", 
            "LaunchedAvailabilityZone": "eu-north-1a", 
            "LaunchSpecification": {
                "Placement": {
                    "Tenancy": "default", 
                    "AvailabilityZone": "eu-north-1a"
                }, 
                "ImageId": "ami-6d27a913", 
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda1", 
                        "VirtualName": "root", 
                        "NoDevice": "", 
                        "Ebs": {
                            "Encrypted": false, 
                            "DeleteOnTermination": true, 
                            "VolumeType": "gp2", 
                            "VolumeSize": 8
                        }
                    }
                ], 
                "EbsOptimized": false, 
                "SecurityGroups": [
                    {
                        "GroupName": "default"
                    }
                ], 
                "Monitoring": {
                    "Enabled": false
                }, 
                "InstanceType": "t3.nano", 
                "AddressingType": "public", 
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0, 
                        "Description": "eth-zero", 
                        "NetworkInterfaceId": "", 
                        "DeleteOnTermination": true, 
                        "SubnetId": "subnet-420ffc2b", 
                        "AssociatePublicIpAddress": true
                    }
                ]
            }, 
            "Type": "one-time", 
            "CreateTime": "2019-02-24T14:55:26.000Z", 
            "SpotPrice": "0.011600"
        }, 
        {
            "Status": {
                "Message": "Your Spot request failed due to bad parameters.", 
                "Code": "bad-parameters", 
                "UpdateTime": "2019-02-24T14:29:24.000Z"
            }, 
            "ActualBlockHourlyPrice": "0.002000", 
            "ValidUntil": "2019-03-03T14:29:23.000Z", 
            "InstanceInterruptionBehavior": "terminate", 
            "Tags": [], 
            "Fault": {
                "Message": "Addressing type must be 'public'", 
                "Code": "InvalidParameterCombination"
            }, 
            "BlockDurationMinutes": 60, 
            "SpotInstanceRequestId": "sir-2jsh5brn", 
            "State": "cancelled", 
            "ProductDescription": "Linux/UNIX", 
            "LaunchedAvailabilityZone": "eu-north-1a", 
            "LaunchSpecification": {
                "Placement": {
                    "Tenancy": "default", 
                    "AvailabilityZone": "eu-north-1a"
                }, 
                "ImageId": "ami-6d27a913", 
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda", 
                        "VirtualName": "root", 
                        "NoDevice": "", 
                        "Ebs": {
                            "Encrypted": false, 
                            "DeleteOnTermination": true, 
                            "VolumeType": "gp2", 
                            "VolumeSize": 8
                        }
                    }
                ], 
                "EbsOptimized": false, 
                "SecurityGroups": [
                    {
                        "GroupName": "default"
                    }
                ], 
                "Monitoring": {
                    "Enabled": false
                }, 
                "InstanceType": "t3.nano", 
                "AddressingType": "", 
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0, 
                        "Description": "eth-zero", 
                        "NetworkInterfaceId": "", 
                        "DeleteOnTermination": true, 
                        "SubnetId": "subnet-420ffc2b", 
                        "AssociatePublicIpAddress": true
                    }
                ]
            }, 
            "Type": "one-time", 
            "CreateTime": "2019-02-24T14:29:23.000Z", 
            "SpotPrice": "0.011600"
        }, 
        {
            "Status": {
                "Message": "Your spot request is fulfilled.", 
                "Code": "fulfilled", 
                "UpdateTime": "2019-02-24T15:37:28.000Z"
            }, 
            "ActualBlockHourlyPrice": "0.002000", 
            "ValidUntil": "2019-03-03T15:37:26.000Z", 
            "InstanceInterruptionBehavior": "terminate", 
            "Tags": [], 
            "InstanceId": "i-0a29e9de6d59d433f", 
            "BlockDurationMinutes": 60, 
            "SpotInstanceRequestId": "sir-z1e9591m", 
            "State": "active", 
            "ProductDescription": "Linux/UNIX", 
            "LaunchedAvailabilityZone": "eu-north-1a", 
            "LaunchSpecification": {
                "Placement": {
                    "Tenancy": "default", 
                    "AvailabilityZone": "eu-north-1a"
                }, 
                "ImageId": "ami-6d27a913", 
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda1", 
                        "VirtualName": "root", 
                        "NoDevice": "", 
                        "Ebs": {
                            "Encrypted": false, 
                            "DeleteOnTermination": true, 
                            "VolumeType": "gp2", 
                            "VolumeSize": 8
                        }
                    }
                ], 
                "EbsOptimized": false, 
                "SecurityGroups": [
                    {
                        "GroupName": "default"
                    }
                ], 
                "Monitoring": {
                    "Enabled": false
                }, 
                "InstanceType": "t3.nano", 
                "AddressingType": "public", 
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0, 
                        "Description": "eth-zero", 
                        "NetworkInterfaceId": "", 
                        "DeleteOnTermination": true, 
                        "SubnetId": "subnet-420ffc2b", 
                        "AssociatePublicIpAddress": true
                    }
                ]
            }, 
            "Type": "one-time", 
            "CreateTime": "2019-02-24T15:37:26.000Z", 
            "SpotPrice": "0.008000"
        }, 
        {
            "Status": {
                "Message": "Your Spot request failed due to bad parameters.", 
                "Code": "bad-parameters", 
                "UpdateTime": "2019-02-24T14:33:43.000Z"
            }, 
            "ActualBlockHourlyPrice": "0.002000", 
            "ValidUntil": "2019-03-03T14:33:42.000Z", 
            "InstanceInterruptionBehavior": "terminate", 
            "Tags": [], 
            "Fault": {
                "Message": "Invalid device name /dev/sda", 
                "Code": "InvalidBlockDeviceMapping"
            }, 
            "BlockDurationMinutes": 60, 
            "SpotInstanceRequestId": "sir-n7c15y5p", 
            "State": "cancelled", 
            "ProductDescription": "Linux/UNIX", 
            "LaunchedAvailabilityZone": "eu-north-1a", 
            "LaunchSpecification": {
                "Placement": {
                    "Tenancy": "default", 
                    "AvailabilityZone": "eu-north-1a"
                }, 
                "ImageId": "ami-6d27a913", 
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/sda", 
                        "VirtualName": "root", 
                        "NoDevice": "", 
                        "Ebs": {
                            "Encrypted": false, 
                            "DeleteOnTermination": true, 
                            "VolumeType": "gp2", 
                            "VolumeSize": 8
                        }
                    }
                ], 
                "EbsOptimized": false, 
                "SecurityGroups": [
                    {
                        "GroupName": "default"
                    }
                ], 
                "Monitoring": {
                    "Enabled": false
                }, 
                "InstanceType": "t3.nano", 
                "AddressingType": "public", 
                "NetworkInterfaces": [
                    {
                        "DeviceIndex": 0, 
                        "Description": "eth-zero", 
                        "NetworkInterfaceId": "", 
                        "DeleteOnTermination": true, 
                        "SubnetId": "subnet-420ffc2b", 
                        "AssociatePublicIpAddress": true
                    }
                ]
            }, 
            "Type": "one-time", 
            "CreateTime": "2019-02-24T14:33:42.000Z", 
            "SpotPrice": "0.011600"
        }
    ]
}

回答by Micha Wiedenmann

If the values don't contain spaces, this might be helpful:

如果值不包含空格,这可能会有所帮助:

read -r -a data <<<'name1 value1 name2 value2'

echo "name value"
echo "=========="

for ((i=0; i<${#data[@]}; i+=2)); do
  echo ${data[$i]} ${data[$((i+1))]}
done

Output

输出

name value
==========
name1 value1
name2 value2