プログラマ行進曲第二章

主にソフトウェア関連の技術をネタにした記事を執筆するためのブログ

jqコマンドのAlternative operatorを初めて知って使った

仕事で必要があって「あるAWSアカウントで使っているRDS for PostgreSQLのバージョン、リソース名などの設定を全リージョン分表示する」ということをしたくて、 jqコマンドを使って色々加工する必要があった時使ったやり方についてメモします。

リージョン毎の区切りとして空行を入れたかったのですが、jqコマンドについて詳しくないこともあり、以下のようなコマンドをxargsと組み合わせてそのまま使ってしまうと、リソース毎の表示に空行がないままで表示されてしまい、各種設定の値がどのリージョンのどのリソースのものなのか分かりづらくなってしまってどうしたらいいのか悩んでいました。

aws rds describe-db-instances | jq .DBInstanceIdentifier,.DBInstanceArn,.EngineVersion,.AutoMinorVersionUpgrade

AutoMinorVersionUpgrade の後に空行を入れられるようにできればいいのですが、jqコマンド直下の箇所なのでechoを入れるわけにもいかず、「jqコマンドに条件分岐に使える式があるかもしれない」と探したところ、StackOverflowか何かでjqコマンドにAlternative Operatorなるものがあることを知りました。

https://stedolan.github.io/jq/manual/#Alternativeoperator://

A filter of the form a // b produces the same results as a, if a produces results other than false and null. Otherwise, a // b produces the same results as b.

これを使ってxargsと組み合わせて、以下のようにコマンドを作り実行して、区切りを空行にして見やすく表示できました*1

$ cat region-rds.txt
us-east-2
us-east-1
us-west-1
us-west-2
ap-south-1
ap-northeast-2
ap-southeast-1
ap-southeast-2
ap-northeast-1
ca-central-1
eu-central-1
eu-west-1
eu-west-2
eu-west-3
eu-north-1
sa-east-1

$ profile=sample
$ cat region-rds.txt | xargs -I{} sh -c "echo [{}]; aws --profile $profile --region {} rds describe-db-instances | jq '.DBInstances[] | select(.Engine == \"postgres\")' | jq -r '.DBInstanceIdentifier,.DBInstanceArn,.EngineVersion,.AutoMinorVersionUpgrade,.Null // \" \"'; echo"
[us-east-2]

[us-east-1]

[us-west-1]

[us-west-2]

[ap-south-1]

[ap-northeast-2]

[ap-southeast-1]

[ap-southeast-2]

[ap-northeast-1]
dev-db-postgresql-1
arn:aws:rds:ap-northeast-1:0001111:db:dev-db-postgresql-2
10.x.x
true

dev-db-postgresql-2
arn:aws:rds:ap-northeast-1:0001111:db:dev-db-postgresql-2
10.x.x
true


[ca-central-1]

[eu-central-1]

[eu-west-1]

[eu-west-2]

[eu-west-3]

[eu-north-1]

[sa-east-1]

実行しているコマンドが長すぎるのはひとえに私のシェル芸能力が低いからですね。

.Null // \" \" で使っている // がAlternative Operatorで、この場合はawscliから帰ってくるjsonのキーに Null なんてものはない(はず)という性質を利用して、本来 null と帰ってくるところを と、空白を返すようにして、区切りとして空行っぽくなるようにしています。

恐らくシェル芸できる力がある人はもっと別のやり方でスマートにできるのかもしれませんし、Alternative Operatorをそんなに使う機会があるとは思えませんが、一つのやり方として知っておいていいのかもしれないとメモしておきます。

*1:少なくとも自分には見やすくできたかと