このドキュメントはStephen Dolan氏が権利を有するコマンドラインプロセッサーjqのマニュアルおよびチュートリアルを、CC-BY-3.0の条件に基づき日本語へ翻訳したものです。

Stephen Dolan氏は日本語版の公開や翻訳について関与するものではありません。

翻訳により混入した誤りや誤字の責任はYuji Okazawaに帰属します。

チュートリアル

GitHubの提供するJSON APIを利用してみましょう。 次のURLにアクセスするとjqのGitHubリポジトリから最新のコミットを5つ取得します。

curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5'
Show result
[
  {
    "sha": "d25341478381063d1c76e81b3a52e0592a7c997f",
    "commit": {
      "author": {
        "name": "Stephen Dolan",
        "email": "mu@netsoc.tcd.ie",
        "date": "2013-06-22T16:30:59Z"
      },
      "committer": {
        "name": "Stephen Dolan",
        "email": "mu@netsoc.tcd.ie",
        "date": "2013-06-22T16:30:59Z"
      },
      "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
      "tree": {
        "sha": "6ab697a8dfb5a96e124666bf6d6213822599fb40",
        "url": "https://api.github.com/repos/stedolan/jq/git/trees/6ab697a8dfb5a96e124666bf6d6213822599fb40"
      },
      "url": "https://api.github.com/repos/stedolan/jq/git/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
      "comment_count": 0
    },
    "url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
    "html_url": "https://github.com/stedolan/jq/commit/d25341478381063d1c76e81b3a52e0592a7c997f",
    "comments_url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f/comments",
    "author": {
      "login": "stedolan",
...

GitHubはきれいに整理されたJSONを返します。 きれいでない応答を返すサーバーがあるときは整形するためにjqとパイプで連結すると便利です。 jqで最も簡潔な式は.です。 入力を変更せずそのまま出力します。

curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'
Show result
[
  {
    "sha": "d25341478381063d1c76e81b3a52e0592a7c997f",
    "commit": {
      "author": {
        "name": "Stephen Dolan",
        "email": "mu@netsoc.tcd.ie",
        "date": "2013-06-22T16:30:59Z"
      },
      "committer": {
        "name": "Stephen Dolan",
        "email": "mu@netsoc.tcd.ie",
        "date": "2013-06-22T16:30:59Z"
      },
      "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
      "tree": {
        "sha": "6ab697a8dfb5a96e124666bf6d6213822599fb40",
        "url": "https://api.github.com/repos/stedolan/jq/git/trees/6ab697a8dfb5a96e124666bf6d6213822599fb40"
      },
      "url": "https://api.github.com/repos/stedolan/jq/git/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
      "comment_count": 0
    },
    "url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
    "html_url": "https://github.com/stedolan/jq/commit/d25341478381063d1c76e81b3a52e0592a7c997f",
    "comments_url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f/comments",
    "author": {
      "login": "stedolan",
...

次のようにすると最初のコミットを取り出すことができます。

curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[0]'
Show result
{
  "sha": "d25341478381063d1c76e81b3a52e0592a7c997f",
  "commit": {
    "author": {
      "name": "Stephen Dolan",
      "email": "mu@netsoc.tcd.ie",
      "date": "2013-06-22T16:30:59Z"
    },
    "committer": {
      "name": "Stephen Dolan",
      "email": "mu@netsoc.tcd.ie",
      "date": "2013-06-22T16:30:59Z"
    },
    "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
    "tree": {
      "sha": "6ab697a8dfb5a96e124666bf6d6213822599fb40",
      "url": "https://api.github.com/repos/stedolan/jq/git/trees/6ab697a8dfb5a96e124666bf6d6213822599fb40"
    },
    "url": "https://api.github.com/repos/stedolan/jq/git/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
    "comment_count": 0
  },
  "url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f",
  "html_url": "https://github.com/stedolan/jq/commit/d25341478381063d1c76e81b3a52e0592a7c997f",
  "comments_url": "https://api.github.com/repos/stedolan/jq/commits/d25341478381063d1c76e81b3a52e0592a7c997f/comments",
  "author": {
    "login": "stedolan",
    "id": 79765,
    "avatar_url": "https://avatars.githubusercontent.com/u/79765?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/stedolan",
    "html_url": "https://github.com/stedolan",
    "followers_url": "https://api.github.com/users/stedolan/followers",
    "following_url": "https://api.github.com/users/stedolan/following{/other_user}",
    "gists_url": "https://api.github.com/users/stedolan/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/stedolan/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/stedolan/subscriptions",
    "organizations_url": "https://api.github.com/users/stedolan/orgs",
    "repos_url": "https://api.github.com/users/stedolan/repos",
    "events_url": "https://api.github.com/users/stedolan/events{/privacy}",
    "received_events_url": "https://api.github.com/users/stedolan/received_events",
    "type": "User",
    "site_admin": false
  },
  "committer": {
    "login": "stedolan",
    "id": 79765,
    "avatar_url": "https://avatars.githubusercontent.com/u/79765?v=3",
    "gravatar_id": "",
    "url": "https://api.github.com/users/stedolan",
    "html_url": "https://github.com/stedolan",
    "followers_url": "https://api.github.com/users/stedolan/followers",
    "following_url": "https://api.github.com/users/stedolan/following{/other_user}",
    "gists_url": "https://api.github.com/users/stedolan/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/stedolan/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/stedolan/subscriptions",
    "organizations_url": "https://api.github.com/users/stedolan/orgs",
    "repos_url": "https://api.github.com/users/stedolan/repos",
    "events_url": "https://api.github.com/users/stedolan/events{/privacy}",
    "received_events_url": "https://api.github.com/users/stedolan/received_events",
    "type": "User",
    "site_admin": false
  },
  "parents": [
    {
      "sha": "54b9c9bdb225af5d886466d72f47eafc51acb4f7",
      "url": "https://api.github.com/repos/stedolan/jq/commits/54b9c9bdb225af5d886466d72f47eafc51acb4f7",
      "html_url": "https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7"
    },
    {
      "sha": "8b1b503609c161fea4b003a7179b3fbb2dd4345a",
      "url": "https://api.github.com/repos/stedolan/jq/commits/8b1b503609c161fea4b003a7179b3fbb2dd4345a",
      "html_url": "https://github.com/stedolan/jq/commit/8b1b503609c161fea4b003a7179b3fbb2dd4345a"
    }
  ]
}

以降の例でもずっと同じなのでcurlコマンドの記述は省略します。

GitHubの応答には気にしないでいい部分がたくさんあるので、最も重要なフィールドだけを残すことにします。

jq '.[0] | {message: .commit.message, name: .commit.committer.name}'
Show result
{
  "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
  "name": "Stephen Dolan"
}

jqの|演算子は前のフィルター.[0](GitHubの応答から配列の最初の要素を取り出します)の出力を 次のフィルター{...}(指定したフィールドを持つオブジェクトを生成します)へ入力します。 .commit.messageのように記述するとネストしたフィールドにアクセスできます。

他のコミットも取得してみましょう。

jq '.[] | {message: .commit.message, name: .commit.committer.name}'
Show result
{
  "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
  "name": "Stephen Dolan"
}
{
  "message": "Reject all overlong UTF8 sequences.",
  "name": "Stephen Dolan"
}
{
  "message": "Fix various UTF8 parsing bugs.\n\nIn particular, parse bad UTF8 by replacing the broken bits with U+FFFD\nand resychronise correctly after broken sequences.",
  "name": "Stephen Dolan"
}
{
  "message": "Fix example in manual for `floor`. See #155.",
  "name": "Stephen Dolan"
}
{
  "message": "Document floor",
  "name": "Nicolas Williams"
}

.[]は配列のそれぞれの要素を1つずつ取り出して、フィルター{message: .commit.message, name: .commit.committer.name}に入力します。

jqはデータをJSON値のストリームとして扱います。 全ての式は入力ストリームのそれぞれの値について実行します。 式は任意の数の値を生成し、出力ストリームへ出力します。

ストリームは空白文字(U+0020)で区切られたJSON値としてシリアライズされます。 catコマンドで扱いやすい形式です。 ですから、ただ2つのJSONストリームを連結しただけでも有効なJSONストリームになります。

出力を単一の配列にしたければ、指定したフィルターを角括弧で囲めばjqに「集約」させることができます。

jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'
Show result
[
  {
    "message": "Merge pull request #163 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
    "name": "Stephen Dolan"
  },
  {
    "message": "Reject all overlong UTF8 sequences.",
    "name": "Stephen Dolan"
  },
  {
    "message": "Fix various UTF8 parsing bugs.\n\nIn particular, parse bad UTF8 by replacing the broken bits with U+FFFD\nand resychronise correctly after broken sequences.",
    "name": "Stephen Dolan"
  },
  {
    "message": "Fix example in manual for `floor`. See #155.",
    "name": "Stephen Dolan"
  },
  {
    "message": "Document floor",
    "name": "Nicolas Williams"
  }
]

次は、GitHub APIの応答から「親コミット」のURLを抽出してみましょう。 GitHub APIの応答にはそれぞれのコミットに「親コミット」の情報が含まれています。 「親コミット」は1つの場合もあるし、複数の場合もあります。

"parents": [
  {
    "sha": "54b9c9bdb225af5d886466d72f47eafc51acb4f7",
    "url": "https://api.github.com/repos/stedolan/jq/commits/54b9c9bdb225af5d886466d72f47eafc51acb4f7",
    "html_url": "https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7"
  },
  {
    "sha": "8b1b503609c161fea4b003a7179b3fbb2dd4345a",
    "url": "https://api.github.com/repos/stedolan/jq/commits/8b1b503609c161fea4b003a7179b3fbb2dd4345a",
    "html_url": "https://github.com/stedolan/jq/commit/8b1b503609c161fea4b003a7179b3fbb2dd4345a"
  }
]

やりたいのは、「親コミット」配列の全ての要素についてフィールド"html_url"を取り出して、 すでに取得できているフィールド"message"や"author"と一緒に、単純な文字列の配列として出力することです。

jq '[.[] | {message: .commit.message, name: .commit.committer.name, parents: [.parents[].html_url]}]'
Show result
[
  {
    "message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
    "name": "Stephen Dolan",
    "parents": [
      "https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7",
      "https://github.com/stedolan/jq/commit/8b1b503609c161fea4b003a7179b3fbb2dd4345a"
    ]
  },
  {
    "message": "Reject all overlong UTF8 sequences.",
    "name": "Stephen Dolan",
    "parents": [
      "https://github.com/stedolan/jq/commit/ff48bd6ec538b01d1057be8e93b94eef6914e9ef"
    ]
  },
  {
    "message": "Fix various UTF8 parsing bugs.\n\nIn particular, parse bad UTF8 by replacing the broken bits with U+FFFD\nand resychronise correctly after broken sequences.",
    "name": "Stephen Dolan",
    "parents": [
      "https://github.com/stedolan/jq/commit/54b9c9bdb225af5d886466d72f47eafc51acb4f7"
    ]
  },
  {
    "message": "Fix example in manual for `floor`. See #155.",
    "name": "Stephen Dolan",
    "parents": [
      "https://github.com/stedolan/jq/commit/3dcdc582ea993afea3f5503a78a77675967ecdfa"
    ]
  },
  {
    "message": "Document floor",
    "name": "Nicolas Williams",
    "parents": [
      "https://github.com/stedolan/jq/commit/7c4171d414f647ab08bcd20c76a4d8ed68d9c602"
    ]
  }
]

前の例と同じようにオブジェクトを作成していますが、ここではフィールドparents.parents[].html_url]を設定しています。 このように記述すると「親コミット」に存在する全てのコミットのURLを集約できます。


チュートリアルはここまでです。 他にもいろいろな使い方があるので、興味があればマニュアルを読んでみましょう。 まだダウンロードしていなければdownload jqからダウンロードしましょう。