jq: создать таблицу, содержащую родительские и связанные дочерние элементы - PullRequest
0 голосов
/ 09 июля 2020

У меня есть json вот так

{
    "NetworkAcls": [
        {
            "Associations": [
                {
                    "NetworkAclAssociationId": "aclassoc-0360bceb2b4788870",
                    "NetworkAclId": "acl-09811190de1965cd4",
                    "SubnetId": "subnet-9fa0aac4"
                },
                {
                    "NetworkAclAssociationId": "aclassoc-08ceb0c1375cb9729",
                    "NetworkAclId": "acl-09811190de1965cd4",
                    "SubnetId": "subnet-db2de5bd"
                }
            ],
            "Entries": [
                {
                    "CidrBlock": "0.0.0.0/0",
                    "Egress": true,
                    "PortRange": {
                        "From": 80,
                        "To": 80
                    },
                    "Protocol": "6",
                    "RuleAction": "allow",
                    "RuleNumber": 100
                },
                {
                    "CidrBlock": "0.0.0.0/0",
                    "Egress": true,
                    "PortRange": {
                        "From": 443,
                        "To": 443
                    },
                    "Protocol": "6",
                    "RuleAction": "allow",
                    "RuleNumber": 200
                }
            ],
            "IsDefault": false,
            "NetworkAclId": "acl-09811190de1965cd4",
            "VpcId": "vpc-12345678",
            "OwnerId": "1234567890"
        },
        {
            "Associations": [
                {
                    "NetworkAclAssociationId": "aclassoc-0531b6837ee6948dc",
                    "NetworkAclId": "acl-0f1c265110106d23d",
                    "SubnetId": "subnet-7f23eb19"
                },
                {
                    "NetworkAclAssociationId": "aclassoc-01314abbaca73ae21",
                    "NetworkAclId": "acl-0f1c265110106d23d",
                    "SubnetId": "subnet-44bdb71f"
                }
            ],
            "Entries": [
                {
                    "CidrBlock": "0.0.0.0/0",
                    "Egress": false,
                    "PortRange": {
                        "From": 80,
                        "To": 80
                    },
                    "Protocol": "6",
                    "RuleAction": "deny",
                    "RuleNumber": 100
                },
                {
                    "CidrBlock": "0.0.0.0/0",
                    "Egress": true,
                    "PortRange": {
                        "From": 443,
                        "To": 443
                    },
                    "Protocol": "7",
                    "RuleAction": "deny",
                    "RuleNumber": 200
                }
            ],
            "IsDefault": false,
            "NetworkAclId": "acl-0f1c265110106d23d",
            "VpcId": "vpc-12345678",
            "OwnerId": "1234567890"
        }
    ]
}

, и мне нужно создать такую ​​таблицу

| NetworkAclId            | RuleNumber    | Egress    | Protocol  | PortRange.From    | PortRange.To  | CidrBlock | RuleAction  |
|-------------------------|---------------|-----------|-----------|-------------------|---------------|-----------|-------------|
| acl-09811190de1965cd4   | 100           | true      | 6         | 80                | 80            | 0.0.0.0/0 | allow       |
| acl-09811190de1965cd4   | 200           | true      | 6         | 443               | 443           | 0.0.0.0/0 | allow       |
| acl-0f1c265110106d23d   | 100           | false     | 6         | 80                | 80            | 0.0.0.0/0 | deny        |
| acl-0f1c265110106d23d   | 200           | true      | 7         | 443               | 443           | 0.0.0.0/0 | deny        |

Entries. * Должен соответствовать только NetworkAclId своего родителя .

Самое близкое, что я получил, было это, но оно производит столько дублирования, что мне приходится его убивать.

.[][] | "\(.Associations[].NetworkAclId) \(.Associations[].SubnetId) \(.Entries[] | .CidrBlock) \(.Entries[] | .Egress) \(.Entries[] | .PortRange.From) \(.Entries[] | .PortRange.To) \(.Entries[] | .Protocol) \(.Entries[] | .RuleAction) \(.Entries[] | .RuleNumber)"

Я не понимаю, что такое jq, поэтому каждое новое поле, которое я добавляю кажется, дает экспоненциально растущие результаты.

Например, это дает 4 результата, как ожидалось:

.[][] | "\(.Associations[].NetworkAclId)"

Но это дает 42 вместо ожидаемых 4.

.[][] | "\(.Associations[].NetworkAclId) \(.Entries[] | .RuleNumber)"

Как мне заставить jq сохранять ассоциации дочерних элементов с родительскими, не связывая все возможные перестановки значений во входных данных?

Спасибо

Ответы [ 2 ]

3 голосов
/ 09 июля 2020

Я нашел формулировку для вывода нужных вам данных в виде CSV:

jq -r '
    .NetworkAcls[] | range(.Associations | length) as $i | [
        .Associations[$i].NetworkAclId,
        (.Entries[$i] |
            .RuleNumber,
            .Egress,
            .Protocol,
            .PortRange.From,
            .PortRange.To,
            .CidrBlock,
            .RuleAction
        )
    ] | @csv
' file.json
"acl-09811190de1965cd4",100,true,"6",80,80,"0.0.0.0/0","allow"
"acl-09811190de1965cd4",200,true,"6",443,443,"0.0.0.0/0","allow"
"acl-0f1c265110106d23d",100,false,"6",80,80,"0.0.0.0/0","deny"
"acl-0f1c265110106d23d",200,true,"7",443,443,"0.0.0.0/0","deny"

Думаю, проще спросить, как преобразовать CSV в таблицу, чем JSON.

2 голосов
/ 09 июля 2020

Вы можете использовать что-то вроде следующего:

.NetworkAcls[] | [.Associations, .Entries] | combinations | \
"\(.[0].NetworkAclId) \(.[1].RuleNumber) \(.[1].Egress) \(.[1].Protocol) \(.[1].PortRange.From) \(.[1].PortRange.To) \(.[1].CidrBlock) \(.[1].RuleAction)"

Попробуйте здесь

Это возвращает 8 элементов, так как есть два элемента NetworkAcls с каждыми двумя ассоциациями и две записи.

...