お金をかけずにサーバーの勉強をしよう

jqコマンド (JSONデータ整形)

2024年4月17日

メニューへ戻る

構造化データの JSONをターミナルで見やすくする。

WebAPIを叩いたり AWSや Azureをコマンドで操作すると、JSON(JavaScript Object Notation)ってフォーマットのデータがズラズラと画面に出てきますよね。

JSONは 1件のデータが 1行ではなく木構造をしていて、{}なんかで囲われて表現されます。

例えば以下は AWSのエミュレーター LocalStackで S3のバケットの中身のリストを取った出力結果です。
[testbucket]バケットには htmlファイルを 10個入れてあります。

subro@Lubuntu2204:~$ aws s3api list-objects --bucket testbucket --endpoint-url=http://UbuntuServer2204-1:4566
{
    "Contents": [
        {
            "Key": "0010.html",
            "LastModified": "2024-04-17T02:01:40.000Z",
            "ETag": "\"ee339b187a0baf89e5f3a07a81187a08\"",
            "Size": 12081,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0020.html",
            "LastModified": "2024-04-17T02:01:45.000Z",
            "ETag": "\"fb054bf42509d10fcedfaa1b50f2a17a\"",
            "Size": 9890,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0030.html",
            "LastModified": "2024-04-17T02:01:49.000Z",
            "ETag": "\"71ade8f630f88045a51d33b674d09573\"",
            "Size": 5030,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0040.html",
            "LastModified": "2024-04-17T02:01:52.000Z",
            "ETag": "\"f9ff55f49f5ff3c7c4fd08561fdfb64e\"",
            "Size": 10358,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0050.html",
            "LastModified": "2024-04-17T02:01:56.000Z",
            "ETag": "\"0efbbe46c1962b3f2e8051e215adca76\"",
            "Size": 11645,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0060.html",
            "LastModified": "2024-04-17T02:01:59.000Z",
            "ETag": "\"67f7cb17b8a4c5e3a88781982aaaf94f\"",
            "Size": 12700,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0070.html",
            "LastModified": "2024-04-17T02:02:03.000Z",
            "ETag": "\"5f5b861a4d583eb44333d101d7bc1a36\"",
            "Size": 18784,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0080.html",
            "LastModified": "2024-04-17T02:02:07.000Z",
            "ETag": "\"cf9cb61ffaa41b4e1a1d5910a8389ffa\"",
            "Size": 13095,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0090.html",
            "LastModified": "2024-04-17T02:02:11.000Z",
            "ETag": "\"e81ff65def3bee4049032954a86dc061\"",
            "Size": 9884,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0100.html",
            "LastModified": "2024-04-17T02:02:14.000Z",
            "ETag": "\"c74055e889113443a4d0ca00ccbe2150\"",
            "Size": 15482,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        }
    ]
}

これでも情報は網羅されていて事足りるのですが、実際に作業してますと、もうちょっと楽に見たいなって思うときがあります。

そんな時のために jqコマンド(Command-line JSON processor)って便利なものがあります。

私は Ubuntu 22.04でやりますが、この OSだと jqコマンドはデフォルトでは入っていないので、パッケージをインストールします。

subro@Lubuntu2204:~$ sudo apt install -y jq

他の Linux OSでも問題なくインストールはできるかと思います。

上のコマンド実行結果をパイプで jqコマンドに渡してみます。
(普段は実行コマンドを緑色にしていますが、ここでは出力結果の色や太字をちゃんと表現したいので、コマンド行を白くして他を実際の出力に似せました。)

subro@Lubuntu2204:~$ aws s3api list-objects --bucket testbucket --endpoint-url=http://UbuntuServer2204-1:4566 | jq
{
    "Contents": [
        {
            "Key": "0010.html",
            "LastModified": "2024-04-17T02:01:40.000Z",
            "ETag": "\"ee339b187a0baf89e5f3a07a81187a08\"",
            "Size": 12081,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0020.html",
            "LastModified": "2024-04-17T02:01:45.000Z",
            "ETag": "\"fb054bf42509d10fcedfaa1b50f2a17a\"",
            "Size": 9890,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0030.html",
            "LastModified": "2024-04-17T02:01:49.000Z",
            "ETag": "\"71ade8f630f88045a51d33b674d09573\"",
            "Size": 5030,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0040.html",
            "LastModified": "2024-04-17T02:01:52.000Z",
            "ETag": "\"f9ff55f49f5ff3c7c4fd08561fdfb64e\"",
            "Size": 10358,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0050.html",
            "LastModified": "2024-04-17T02:01:56.000Z",
            "ETag": "\"0efbbe46c1962b3f2e8051e215adca76\"",
            "Size": 11645,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0060.html",
            "LastModified": "2024-04-17T02:01:59.000Z",
            "ETag": "\"67f7cb17b8a4c5e3a88781982aaaf94f\"",
            "Size": 12700,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0070.html",
            "LastModified": "2024-04-17T02:02:03.000Z",
            "ETag": "\"5f5b861a4d583eb44333d101d7bc1a36\"",
            "Size": 18784,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0080.html",
            "LastModified": "2024-04-17T02:02:07.000Z",
            "ETag": "\"cf9cb61ffaa41b4e1a1d5910a8389ffa\"",
            "Size": 13095,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0090.html",
            "LastModified": "2024-04-17T02:02:11.000Z",
            "ETag": "\"e81ff65def3bee4049032954a86dc061\"",
            "Size": 9884,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        },
        {
            "Key": "0100.html",
            "LastModified": "2024-04-17T02:02:14.000Z",
            "ETag": "\"c74055e889113443a4d0ca00ccbe2150\"",
            "Size": 15482,
            "StorageClass": "STANDARD",
            "Owner": {
                "DisplayName": "webfile",
                "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
            }
        }
    ]
}

実際はもっとカラフルな感じですが、CSSで表現するとどうもおとなしくなってしまいました。

フォーマットは同じながらも、カッコや記号が太字になる、キーは青字で、値が文字列だと緑色とか、見やすくなっていますよね。

ここでの例示に使った awsコマンドはもとから JSON出力が整形されているのですが、他のコマンドや WebAPI等の出力でインデント・改行がない場合(1行でズルズル出る)でもキレイに整形してくれます。

この JSONデータの構成は以下のようになっていて、jqコマンドで特定の箇所だけ抽出することができます。

. (ルート)
└Contents[]
 ├Key
 ├LastModified
 ├ETag
 ├Size
 ├StorageClass
 └Owner
  ├DisplayName
  └ID

例えばファイル名(Key)だけ。

subro@Lubuntu2204:~$ aws s3api list-objects --bucket testbucket --endpoint-url=http://UbuntuServer2204-1:4566 | jq '.Contents[].Key'
"0010.html"
"0020.html"
"0030.html"
"0040.html"
"0050.html"
"0060.html"
"0070.html"
"0080.html"
"0090.html"
"0100.html"

DisplayNameだけ。

subro@Lubuntu2204:~$ aws s3api list-objects --bucket testbucket --endpoint-url=http://UbuntuServer2204-1:4566 | jq '.Contents[].Owner.DisplayName'
"webfile"
"webfile"
"webfile"
"webfile"
"webfile"
"webfile"
"webfile"
"webfile"
"webfile"
"webfile"

コマンドオプションの、階層に対応する書き方は分かりましたでしょうか。

[Contents]配列を取得してから、[Key]キーの値が [0010.html]のものだけ。

subro@Lubuntu2204:~$ aws s3api list-objects --bucket testbucket --endpoint-url=http://UbuntuServer2204-1:4566 | jq '.Contents[] | select(.Key=="0010.html")'
{
    "Key": "0010.html",
    "LastModified": "2024-04-17T02:01:40.000Z",
    "ETag": "\"ee339b187a0baf89e5f3a07a81187a08\"",
    "Size": 12081,
    "StorageClass": "STANDARD",
    "Owner": {
        "DisplayName": "webfile",
        "ID": "75aa57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a"
    }
}

どうですか?使い方が何となく分かりましたでしょうか。

WebAPIの引数でごちゃごちゃ書くより楽で良いでしょう?


==========
jqコマンドの機能はもっと一杯あって、色々と JSONデータの加工ができます。

ただ私個人の感想ですけど、サーバー構築の時に利用したのは上に書いた程度で十分でした。

それでもこのコマンドを使えると使えないでは随分と違いますので、大変に重宝しているという塩梅です。

GUIが使える環境ならこのコマンドに頼らなくても良い GUIツールが色々とあるんですが、私達サーバーエンジニアが活躍するのは黒い画面を通して使っているリモート先のサーバーですので、こういったコマンドでゴニョゴニョする手を持っていれば、何かと楽になる(ミスも減る)のです。

このような時代ですし、jqコマンドはできれば OSの標準としてデフォルトで載せておいてくれると助かりますけどね。

Linuxサーバーを作る際には、環境構築の要件の一つとして、お客さんにこのコマンドのインストールを要求してみてはどうかと思うほどです。


このコマンドだけで本が 2冊も!