jqコマンドは、JSONを整形し、必要な値だけを取り出し、別の形に組み替えるためのコマンドラインツールです。curlで叩いたWeb APIの応答やAWS CLIの出力を、パイプ1本で読みやすい形や表計算向けのCSVへ変えられます。この記事では、インストールと版の確認から、selectやmapによる絞り込み、シェル変数の安全な渡し方、CIで使う終了コード、AWS CLI・GitHub CLIとの組み合わせまで、コピーして動かせる実行例で解説します。2026年9月時点の最新版は1.8.2で、Ubuntuのaptで入る版とは差がある点も整理しました。コマンドライン操作そのものが初めての場合はCLIとは?コマンドライン操作の仕組みとGUIとの使い分けを先に読むと手順を追いやすくなります。
まとめ:jqコマンドを実務で使う前に押さえる版とフィルタの5点
1つ目は版です。公式の最新は2026年6月20日公開の1.8.2で、CVE番号付きの脆弱性修正が16件入りました。Ubuntu 24.04のaptで入るのは1.7.1、22.04では1.6です。jq --versionで自分の環境の版を先に確かめてください。
2つ目は基本の形です。jq 'フィルタ' ファイルが全ての出発点で、.が入力全体、|が次のフィルタへの受け渡しを表します。文字列を引用符なしで取り出すなら-rを付けます。
3つ目はシェル変数の渡し方です。フィルタの文字列に変数を埋め込まず、--argか--argjsonで渡します。
4つ目はCIでの使い方で、-eを付けると結果がfalseかnullのときに終了コード1を返します。
5つ目は引き際です。複数ファイルの結合やテストが要る変換までjqで抱えると保守できなくなります。その線引きは最後の章で言い切ります。
jqをLinux・macOS・Windowsにインストールして版を確かめる手順
jqは依存ライブラリの少ない単体のバイナリで、主要なパッケージマネージャーから入れられます。入れ方によって入る版が変わる点だけ注意してください。
apt・brew・wingetのインストールコマンドと入る版の違い
jq公式のダウンロードページに載っているコマンドは次のとおりです。
# Debian / Ubuntu
sudo apt-get install -y jq
# macOS(Homebrew)
brew install jq
# Windows(winget)
winget install jqlang.jq
# 入った版を確認
jq --version
HomebrewとwingetはおおむねGitHubの最新リリースに追従します。LinuxディストリビューションのパッケージはOSのリリース時点の版で固定され、以後はセキュリティ修正だけが取り込まれるのが通例です。最新の1.8.2を確実に使いたい場合は、公式ページから単体のバイナリを取得してPATHの通った場所へ置く方法もあります。Windowsのarm64向けバイナリは1.8.2で初めて用意されました。
Ubuntu 24.04のaptで入る1.7.1と公式最新1.8.2の差
Ubuntuのパッケージ検索で2026年9月時点の版を確かめると、次のようになっています。
| Ubuntuの版 | aptで入るjq | 使えない主な機能 |
|---|---|---|
| 22.04 LTS | 1.6系 | pick、--raw-output0、trim |
| 24.04 LTS | 1.7.1系 | trim、trimstr、skip |
| 26.04 LTS | 1.8.1系 | 1.8.2の修正分のみ |
ネット上の記事のフィルタが手元で動かないとき、原因の多くはこの版差です。CIのランナーと開発機で版が違うと「手元では通るのにCIで落ちる」という事態も起きます。チームで使うスクリプトは、どの版で動かす前提かをREADMEに1行書いておくと調査の手間が減ります。
JSONを整形して値を取り出すjqの基本フィルタと主要オプション
ここからは次のusers.jsonを例に進めます。ファイルに保存しておけば、以降のコマンドをそのまま試せます。
{"users":[{"id":1,"name":"sato","role":"admin","active":true},{"id":2,"name":"suzuki","role":"dev","active":false},{"id":3,"name":"tanaka","role":"dev","active":true}]}
jq ‘.’で整形しドットとパイプで入れ子の値を取り出す書き方
フィルタの.は「入力そのもの」を意味します。何も加工せずに渡すと、インデント付きで色分けされた読みやすいJSONが返ります。
jq '.' users.json
jq '.users[0].name' users.json # "sato"
jq '.users | length' users.json # 3
jq '.users[-1] | .name' users.json # "tanaka"
.users[0].nameのようにドットでキーをつなぎ、角括弧で配列の位置を指定します。負の番号を指定した場合は、末尾から数える仕組みです。|は左の結果を右のフィルタの入力にする演算子で、.users | lengthは「usersの配列を取り出し、その要素数を数える」と読みます。存在しないキーを指定してもエラーにはならずnullが返る点は覚えておいてください。JSONの型とnullの扱いはJSONの型定義とデータ型一覧で整理しています。
入力にコメントが入っているとjqは構文エラーで止まります。設定ファイルがJSONCやJSON5で書かれている場合の読み方はJSONはコメントアウトできない?JSONC・JSON5の書き方を参照してください。
-rと-cと-sで出力形式を切り替える用途別のオプションの使い分け
実務で頻繁に付けるオプションは次の4つです。
| オプション | 働き | 使う場面 |
|---|---|---|
-r |
文字列を引用符なしで出す | 値をシェル変数やほかのコマンドへ渡す |
-c |
1件を1行に詰めて出す | NDJSONの生成、grepとの併用 |
-s |
入力全体を1つの配列に読み込む | 複数のJSONをまとめて集計する |
-n |
入力を読まずにnullから始める |
inputsで1件ずつ読む、JSONを新規作成 |
jq -r '.users[].name' users.json # sato / suzuki / tanaka が1行ずつ
jq -c '.users[]' users.json # 1ユーザー1行のJSON
name=$(jq -r '.users[0].name' users.json)
echo "$name" # sato
-rを付け忘れると、変数に"sato"と引用符ごと入り、後続の比較が一致しなくなります。シェルへ値を渡す場面では-rを既定と考えてよいくらいです。値に改行を含む可能性があるなら、1.7で追加された--raw-output0でNUL区切りにし、xargs -0で受けます。
配列を.[]で展開しmapとselectで条件抽出する実行例
配列の要素を1件ずつ流すのが.[]、条件に合う要素だけを残すのがselectです。
# 有効なユーザーの名前だけを配列で
jq '[.users[] | select(.active) | .name]' users.json
# ["sato","tanaka"]
# role が dev のユーザーを id と name だけに絞る
jq '.users | map(select(.role == "dev") | {id, name})' users.json
# role ごとの人数を集計
jq '.users | group_by(.role) | map({role: .[0].role, count: length})' users.json
# [{"role":"admin","count":1},{"role":"dev","count":2}]
map(f)は[.[] | f]の短縮形なので、1つ目と2つ目は同じ考え方で書けます。{id, name}は{id: .id, name: .name}の省略記法です。.users[] | select(...)のように角括弧で囲まないと結果が1件ずつばらばらに出るため、後で件数を数えたいなら配列で包む、と覚えておくと迷いません。
シェルスクリプトとCIでjqを使うときの変数渡しと終了コード
対話的に眺めるだけなら前章で足ります。スクリプトに組み込むと、変数の渡し方と失敗の検知が問題になります。
–argと–argjsonでシェル変数を安全に渡す書き方と注意点
フィルタを二重引用符で囲んで変数を展開する書き方は避けてください。値に引用符や|が含まれると、フィルタの構文そのものが変わってしまいます。jq 1.8 Manualが用意している正規の渡し方は次のとおりです。
role="dev"
jq -r --arg role "$role" '.users[] | select(.role == $role) | .name' users.json
min=2
jq -c --argjson min "$min" '.users[] | select(.id >= $min)' users.json
ここでつまずきやすいのが型です。マニュアルにあるとおり--argは値を文字列として束縛するため、--arg min 2と書くと$minは"2"になり、数値のidと比較しても一致しません。数値や真偽値、JSONのオブジェクトを渡すときは--argjsonを使うか、フィルタ側で($min | tonumber)と変換します。環境変数は$ENV.HOMEのように直接読むこともできます。
-eで終了コードを使い分けCIの成功・失敗の判定条件に組み込む方法
jqは通常、フィルタが実行できれば結果の中身にかかわらず終了コード0を返します。-e(--exit-status)を付けると、マニュアルの定義どおり次のように変わります。
- 最後の出力が
falseでもnullでもない:0 - 最後の出力が
falseかnull:1 - 有効な結果が1つも出なかった:4
- 使い方の誤りやファイルが無いなどのエラー:2、フィルタの構文エラー:3
# ヘルスチェックの応答が {"status":"ok"} でなければ失敗させる
curl -fsS "$HEALTH_URL" | jq -e '.status == "ok"' > /dev/null
echo $? # ok なら 0、それ以外なら 1
# 設定ファイルに必須キーがあるかを確かめる
if ! jq -e '.database.host' config.json > /dev/null; then
echo "database.host がありません" >&2
exit 1
fi
GitHub Actionsのステップは終了コードが0以外なら失敗扱いになるため、上の1行をそのままrun:に書けばデプロイ後の疎通確認になります。注意点は、1を「値が偽」、2と3を「jq自体の失敗」と分けて扱うことです。|| trueでまとめて握りつぶすと、フィルタの書き間違いまで見逃します。
@csvと@tsvでAPIの応答を表計算用のCSVへ変換する手順
@csvと@tsvは、配列を1行のCSVまたはTSVに変換する書式です。入力が配列でなければならない点がマニュアルに明記されています。
# 見出し行つきでCSVに変換
jq -r '["id","name","role"], (.users[] | [.id, .name, .role]) | @csv' users.json > users.csv
# "id","name","role"
# 1,"sato","admin"
# TSVなら区切りがタブになり、文字列に引用符が付かない
jq -r '.users[] | [.id, .name, .role] | @tsv' users.json
-rを付けないと、CSVの1行全体がさらにJSON文字列として引用符で囲まれて出てきます。もう1つ、jqの出力はBOMなしのUTF-8なので、日本語を含むCSVをExcelでそのまま開くと文字化けすることがあります。その場合は先頭にBOMを書いてから、CSVの内容を追記してください。
printf '\xEF\xBB\xBF' > users.csv
jq -r '.users[] | [.id, .name, .role] | @csv' users.json >> users.csv
AWS CLI・GitHub CLI・curlの出力をjqで加工する実務パターン
jqが最も出番の多い場面は、ほかのCLIが返すJSONの後処理です。ただし各CLIには独自の絞り込み機能もあるため、どちらを使うかの基準を先に決めておきます。
AWS CLIの–queryとjqを使い分ける基準とサーバー側フィルタ
AWS CLIのフィルタリングに関する公式ガイドでは、--filtersなどのサーバー側フィルタと、JMESPath構文による--queryのクライアント側フィルタが区別されています。大量のリソースを扱うときは、まずサーバー側で件数を減らすのが基本です。
# 起動中のEC2だけをサーバー側で絞り、ID・Nameタグ・種類をTSVで出す
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--output json \
| jq -r '.Reservations[].Instances[]
| [.InstanceId,
(first(.Tags[]? | select(.Key == "Name") | .Value) // "-"),
.InstanceType]
| @tsv'
取り出して並べるだけなら--queryで足ります。jqに渡す価値があるのは、タグが無いときの既定値(// "-")、複数のコマンドの結果の突き合わせ、CSV化のように、JMESPathでは書きにくい処理です。同じガイドは、--output textでは出力がページ単位に分割されてから--queryが適用されると注意しています。jqへ渡すときは--output jsonを明示してください。認証やプロファイルの設定はAWS CLIの導入と運用にまとめています。
gh –jqでjq未導入の環境でもGitHubの応答を絞り込む方法
GitHub CLIは--jsonと--jqの組み合わせで出力を絞れます。GitHub CLIのフォーマット解説には、この書式を使うためにjqをシステムへインストールする必要はないと書かれています。
# 自分のリポジトリのオープンなPRを「番号 作成者 タイトル」で一覧
gh pr list --json number,author,title \
--jq '.[] | "\(.number)\t\(.author.login)\t\(.title)"'
\(...)は文字列の中に式の値を埋め込む書き方で、jq本体でも同じように使えます。jqを入れられない社内の端末やCIのイメージでも、GitHubの情報を取るだけならこの方法で済みます。ghそのものの導入はghコマンド(GitHub CLI)のインストール方法と使い方を参照してください。
curlでWeb APIを叩きページングやNDJSONをjqで処理する例
公開APIの応答を整形する例として、jq自身のリリース一覧を取得してみます。認証なしで動きます。
curl -s "https://api.github.com/repos/jqlang/jq/releases?per_page=3" \
| jq -r '.[] | [.tag_name, .published_at[:10]] | @tsv'
# jq-1.8.2 2026-06-20
# jq-1.8.1 2025-07-01
# jq-1.8.0 2025-06-01
.published_at[:10]は文字列の先頭10文字を切り出す指定で、日時から日付だけを残しています。件数の多いAPIではpageを1つずつ増やしながら取得し、各ページの配列をjq -s 'add'で1つの配列につなげると後の集計が楽です。1行に1つのJSONが並ぶNDJSON形式のログは、-cと-n・inputsの組み合わせで処理します。
# level が error の行だけを抜き出す
jq -c 'select(.level == "error")' app.log
# error の件数を数える(全件をメモリに載せずに1件ずつ読む)
jq -n '[inputs | select(.level == "error")] | length' app.log
ログをJSONで出す設計そのものは構造化ログとは|JSONでログを機械可読にする仕組み、NDJSONを検索基盤へ投入する処理はElasticsearchのデータ投入|bulk APIのNDJSON形式で扱っています。
jq 1.7から1.8への版差で動かないフィルタと更新判断の基準
ここからは使い方ではなく、どの版を使い、どこでjqをやめるかの判断です。リリースノートの記載を根拠に言い切ります。
trimやpickが古い版で使えないときに出るエラーと回避策
jq 1.8.0のリリースノートには、trim・ltrim・rtrim・trimstr・skipなどの関数が新たに加わったと記されています。1.7.1以前でこれらを使うと「trim/0 is not defined」というコンパイルエラーになり、終了コード3で停止する仕様です。pickと--raw-output0は1.7で入ったため、1.6では同じように失敗します。
# 1.8以降
jq -r '.name | trim' data.json
# 1.6〜1.7.1でも動く書き方(正規表現で前後の空白を除く)
jq -r '.name | sub("^\\s+"; "") | sub("\\s+$"; "")' data.json
逆方向の変更もあります。1.8.0では、ltrimstrとrtrimstrが文字列以外の入力でエラーを返すようになり、limitに負の数を渡すとエラー、index系の位置はバイト単位からコードポイント単位へ変わりました。日本語を含む文字列でindexの結果を使っているスクリプトは、1.7から上げたときに値がずれます。複数の版が混在する環境では、共通部分の関数だけで書くのが安全です。
1.8.2の16件の脆弱性修正を受けて更新すべき環境と入力データの条件
jq 1.8.2のリリースノートには、ヒープバッファオーバーフロー、深い入れ子によるスタックオーバーフロー、ハッシュ衝突を使ったサービス拒否への対策など、CVE番号付きの修正が16件並んでいます。出力の最大の深さも256から10000へ引き上げられました。
更新を急ぐべきなのは、外部から受け取ったJSONをjqに通している環境です。具体的には、Webhookの受信内容をシェルで処理するサーバー、第三者のAPI応答をそのままjqで加工するバッチ、利用者がアップロードしたファイルを検査するCIが当てはまります。自分で生成した設定ファイルを読むだけの開発機なら、OSのパッケージ更新に任せて構いません。Ubuntuのパッケージは版番号が1.7.1のままでもセキュリティ修正が個別に取り込まれるため、jq --versionだけで判断せず、apt changelog jqで修正の有無を確かめてください。
jqを使わずPythonやスクリプト言語に切り替えるべき場面
jqをやめるべき条件ははっきりしています。フィルタが-fで別ファイルに切り出すほど長くなった場合、2つ以上のJSONをキーで突き合わせる結合が必要になった場合、変換結果を単体テストで保証したい場合の3つです。どれか1つでも当てはまれば、PythonやNode.jsのスクリプトに移します。jqのフィルタはレビューで読める人が限られ、壊れても型の検査が効きません。
入力の構造そのものを保証したいなら、jqでhasを並べるよりJSON Schemaで構造を検証する方法のほうが意図が伝わります。WindowsでJSONを扱う作業が中心なら、ConvertFrom-Jsonを標準で持つPowerShell 7を使う選択肢もあり、導入はPowerShellのインストール手順で解説しています。
シェルとjqで組んだシステム間のデータ受け渡しが、件数の増加や連携先の追加で回らなくなってきたら、それは連携処理を設計し直す時期です。API連携の設計と実装はAPI開発・システム連携でご相談いただけます。
よくある質問
jqコマンドで検索されることの多い疑問に答えます。
Windowsのコマンドプロンプトでjqのフィルタがエラーになるのはなぜですか?
コマンドプロンプト(cmd.exe)は単一引用符を引用符として扱わないため、jq '.users[0]' users.jsonの'がそのままjqに渡って構文エラーになります。cmd.exeではjq ".users[0].name" users.jsonのように二重引用符で囲み、フィルタ内の文字列は\"でエスケープします。引用符の扱いで悩むくらいなら、フィルタをfilter.jqというファイルに書いてjq -f filter.jq users.jsonで読ませるのが確実です。
キーにハイフンや記号が含まれる場合はどう書きますか?
.user-nameと書くと、jqは.userからnameを引く計算と解釈します。キーを文字列として指定し、.["user-name"]または."user-name"と書いてください。数字で始まるキーや日本語のキーも同じ書き方で取り出せます。シェル側の引用符と衝突しないよう、フィルタ全体は単一引用符で囲みます。
jqで値を書き換えて元のファイルに保存できますか?
jq自体に上書き保存の機能はありません。jq '.version = "2.0.0"' package.json > package.jsonのように同じファイルへリダイレクトすると、jqが読む前にシェルがファイルを空にしてしまい、中身が消えます。一時ファイルへ書き出してから置き換えてください。例:jq '.version = "2.0.0"' package.json > tmp.json && mv tmp.json package.json。
存在しないキーやnullはどう扱われますか?
オブジェクトに無いキーを指定すると、エラーではなくnullが返ります。既定値を入れたい場合は.timeout // 30のように//を使うと、左がnullかfalseのときに採用されるのは右の値です。入力が配列や文字列でキーを引けない場合はエラーになりますが、.foo?と書けばエラーを抑えられます。キーの有無を判定に使うなら-eと組み合わせます。
jqとyqは何が違いますか?
jqはJSON専用で、yqはYAMLを主な対象にしたツールです。yqという名前のツールは2系統あり、Go製のmikefarah版はjqに似た独自の構文を持ち、Python製のkislyuk版は内部でjqを呼び出します。KubernetesのマニフェストやGitHub Actionsのワークフローを書き換えるならyq、APIの応答やCLIの出力を加工するならjq、と入力の形式で選んでください。
関連記事
- CLIとは?コマンドライン操作の仕組みとGUIとの使い分けを実装視点で解説:jqを含むコマンドライン操作の前提知識です。
- AWS CLIの導入と運用|v2の設定・SSO認証・v1サポート終了への移行手順:jqと組み合わせることの多いAWS CLIの設定手順です。
- 構造化ログとは|JSONでログを機械可読にする仕組みとslog/structlog実装:jqで検索しやすいログを出す側の設計です。
- JSON Schemaとは?JSONの構造を検証する書き方とDraft 2020-12の実装:jqの手前で入力の構造を保証する方法です。
- Nushellとは?次世代シェルの特徴・インストール・基本コマンドを解説:JSONを表として扱えるシェルで、jqとは別の選択肢になります。