#json #key #jq
#json #Клавиша #jq
Вопрос:
У меня есть следующий json:
{
"SecurityGroups": [
{
"Description": "SG for ssh-proxy server",
"GroupName": "ssh-proxy-SG",
"IpPermissions": [
{
"FromPort": 161,
"IpProtocol": "udp",
"IpRanges": [],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 161,
"UserIdGroupPairs": [
{
"GroupId": "sg-22e04e44",
"UserId": "XXXXXXXXXXXX"
}
]
},
{
"FromPort": 22,
"IpProtocol": "tcp",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 22,
"UserIdGroupPairs": []
},
{
"FromPort": -1,
"IpProtocol": "icmp",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": -1,
"UserIdGroupPairs": []
}
],
"OwnerId": "XXXXXXXXXXXX",
"GroupId": "sg-4f1d8a35",
"IpPermissionsEgress": [
{
"IpProtocol": "-1",
"IpRanges": [
{
"CidrIp": "0.0.0.0/0"
}
],
"Ipv6Ranges": [],
"PrefixListIds": [],
"UserIdGroupPairs": []
}
],
"Tags": [
{
"Key": "Name",
"Value": "ssh-proxy-SG"
}
],
"VpcId": "vpc-d3131fbe"
}
]
}
Используя jq
, я пытаюсь отобразить такой список:
161 tcp sg-22e04e44
22 tcp 0.0.0.0/0
-1 icmp 0.0.0.0/0
Я могу напечатать только порт и протокол, но не «.IpRanges[].CidrIp», вот так:
✗ aws ec2 describe-security-groups --group-id sg-4f1d8a35 --profile XXXX --region us-east-1 --output json | jq -r '.SecurityGroups[].IpPermissions[] | (.FromPort|tostring) " " .IpProtocol'
161 udp
22 tcp
-1 icmp
Проблема в том, что иногда (в данном случае в правиле 161 udp) отсутствует «.IpRanges[].CidrIp» и это вызывает ошибку.
Я пробовал это:
✗ aws ec2 describe-security-groups --group-id sg-4f1d8a35 --profile XXXXXXX --region us-east-1 --output json | jq -r '.SecurityGroups[].IpPermissions[] | (.FromPort|tostring) " " .IpProtocol " " .IpRanges[].CidrIp'
22 tcp 0.0.0.0/0
-1 icmp 0.0.0.0/0
Но, как вы можете видеть, строка udp отсутствует.
Также пробовал это:
✗ aws ec2 describe-security-groups --group-id sg-4f1d8a35 --profile XXXXXXX --region us-east-1 --output json | jq -r '.SecurityGroups[].IpPermissions[] | .IpRanges[]? |= if has(.CidrIp) then (.FromPort|tostring) " " .IpProtocol " " .IpRanges[].CidrIp else (.FromPort|tostring) " " .IpProtocol " " .UserIdGroupPairs[].GroupId end'
{
"FromPort": 161,
"IpProtocol": "udp",
"IpRanges": [],
"Ipv6Ranges": [],
"PrefixListIds": [],
"ToPort": 161,
"UserIdGroupPairs": [
{
"GroupId": "sg-22e04e44",
"UserId": "XXXXXXX"
}
]
}
jq: error (at <stdin>:72): Cannot iterate over null (null)
Что я делаю не так?
Комментарии:
1. Вы заметили, что
CidrIP
отсутствует дляudp
записи2. Да, забыл упомянуть об этом, именно в этом моя проблема
3. Вам нужна пустая строка для этого? Как должен выглядеть ваш вывод?
4. 161 tcp sg-22e04e44 22 tcp 0.0.0.0/0 -1 icmp 0.0.0.0/0
5. Ах, я думал, что // это комментарий, и не включил его в свою команду, он работает отлично. Извините за недоразумение, не могли бы вы, пожалуйста, вернуть свой ответ?
Ответ №1:
CidrIP
Отсутствует для udp
записи. Если вы хотите чередовать .GroupId
и CidrIp
, вы можете выполнить чередование следующим образом
.SecurityGroups[].IpPermissions[] |
.FromPort as $port |
.IpProtocol as $prot |
.IpRanges as $ip |
.UserIdGroupPairs as $group |
[
($port|tostring),
($prot),
(select($ip|length) | $ip[].CidrIp) //
(select($group|length) | $group[].GroupId) //
empty
] |
@tsv
выдает результат, подобный тому, который вы хотели
161 udp sg-22e04e44
22 tcp 0.0.0.0/0
-1 icmp 0.0.0.0/0
Вы можете использовать --raw-output/-r
режим вместе с любым из @csv
, @tsv
или join(" ")
для представления выходных данных в табличной форме.
Комментарии:
1. Это не то, что я пытаюсь сделать, в правиле udp я пытаюсь отобразить «.UserIdGroupPairs. Идентификатор группы » if «.IpRanges[]» не содержит «.CidrIp» .
2. Смотрите правки. Показанный код выдает именно такой результат
3. Предупреждение: Проверка того, существует ключ или нет, может быть выполнена непосредственно с помощью
has/1
, но не//
в одиночку. Причина в том, что если FOO вычисляется до единственного значения, скажем, $ foo, тоFOO // BAR
вычисляется до BAR, если $ foo равно false или null.4. @peak: надеюсь, теперь лучше
5. Хм.
jq -n '([],{},0,null) | select(length)'
выдает: [] {} 0 null