【完全リファレンス】jqコマンドのオプション一覧と使い方|実用例80超で徹底解説
- 作成日 2026.06.19
- linux
jqはLinux/macOSでJSONを処理するための定番コマンドラインツールです。APIレスポンスの整形から特定フィールドの抽出、条件フィルタ、集計まで、エンジニアのJSON作業を一手に担います。しかし、
.foo.bar程度は書けるが応用になると手が止まる- 配列のフィルタ・変換の書き方が分からない
--argと--argjsonの違いが曖昧select・map・reduceなどの関数の使い分けcurlとの連携でよくハマるポイント- ネストが深いJSONをうまく平坦化したい
- 条件分岐・エラー処理の書き方
など、使いこなすには体系的な知識が必要です。
本記事では、jqコマンドの全主要オプションと実用パターンを、リファレンスとして完全網羅しました。基本フィルタから型操作・関数・高度なフィルタ・curl連携・80超の実用例・FAQまで、この1本をブックマークすればjqのあらゆる疑問が解決します。
目次
- 1. インストール
- 2. 結論:今すぐ使える基本パターン5選
- 3. 基本構文
- 4. オプション一覧表
- 5. 基本フィルタ
- 6. 型と値の操作
- 7. 配列操作
- 8. オブジェクト操作
- 9. 条件分岐
- 10. 文字列操作
- 11. 数値演算
- 12. 変数・関数定義
- 13. 再帰処理(.. と recurse)
- 14. reduce と foreach
- 15. –arg / –argjson でシェル変数を渡す
- 16. curl との連携(最重要)
- 17. 実用パターン集(80超を厳選)
- 18. スクリプトファイル(-f)
- 19. パフォーマンス Tips
- 20. macOS / 環境差異に関する注意
- 21. トラブルシューティング
- 22. よくある質問(FAQ)
- 23. 参考リンク・関連資料
- 24. まとめ
インストール
# Ubuntu / Debian
sudo apt install jq
# macOS(Homebrew)
brew install jq
# RHEL / CentOS / Fedora
sudo dnf install jq
# Alpine Linux
apk add jq
# バイナリ直接取得(CI環境等)
curl -L https://github.com/jqlang/jq/releases/latest/download/jq-linux-amd64 -o /usr/local/bin/jq
chmod +x /usr/local/bin/jq
# バージョン確認
jq --version
結論:今すぐ使える基本パターン5選
時間がない方向けに、超頻出パターンを先に示します。
# ① JSONを整形して表示
echo '{"name":"Alice","age":30}' | jq '.'
# ② 特定フィールドを取得
curl -s https://api.example.com/user | jq '.name'
# ③ 配列の全要素から特定フィールドを抽出
jq '[.[] | .name]' users.json
# ④ 条件でフィルタ
jq '.[] | select(.age > 20)' users.json
# ⑤ 複数フィールドで新しいオブジェクトを構築
jq '.[] | {name: .name, email: .email}' users.json
詳細・応用は以下で順に解説します。
基本構文
jq [オプション] フィルタ [ファイル...]
入力のパターン
# ファイルから読み込み
jq '.' data.json
# 標準入力から
echo '{"key":"value"}' | jq '.'
cat data.json | jq '.'
# 複数ファイル
jq '.' file1.json file2.json
# 改行区切りのJSON(NDJSON / JSON Lines)
jq '.' --seq data.ndjson
jq -s '.' *.json # 複数JSONを配列として読み込む
出力の仕組み
jqはデフォルトで色付き・整形済みのJSONを標準出力に出力します。
# 整形出力(デフォルト)
jq '.' data.json
# 1行に圧縮(-c)
jq -c '.' data.json
# 文字列として出力(-r)
jq -r '.name' data.json # "Alice" ではなく Alice と出力
# 出力なし(終了コードだけ使う)
jq -e '.name' data.json > /dev/null && echo "name exists"
オプション一覧表
入力制御
| オプション | 説明 |
|---|---|
-s / --slurp | 全入力を1つの配列として読み込む |
-R / --raw-input | 各行を文字列として読み込む(JSONとして解釈しない) |
-n / --null-input | 入力を読まず null を入力として使う |
--seq | RFC 7464 シーケンス形式で読み込む |
--stream | ストリーミング形式で解析(巨大JSONに有効) |
出力制御
| オプション | 説明 |
|---|---|
-c / --compact-output | 整形せず1行で出力 |
-r / --raw-output | 文字列の引用符なしで出力 |
-R / --raw-output0 | NUL文字区切りで出力(xargs -0 と組み合わせ) |
-j / --join-output | 改行を追加しない(-r + 改行なし) |
-e / --exit-status | 出力が false/null なら終了コード1 |
--tab | インデントにタブを使う |
--indent N | インデント幅をN(1〜7)に設定 |
--color-output / -C | 色付き出力を強制(リダイレクト時も) |
--monochrome-output / -M | 色なし出力 |
--ascii-output / -a | ASCII以外の文字を \uXXXX にエスケープ |
--sort-keys / -S | キーをアルファベット順に並べ替えて出力 |
変数・引数渡し
| オプション | 説明 |
|---|---|
--arg name value | 文字列変数を $name として渡す |
--argjson name json | JSON値を $name として渡す |
--slurpfile name file | ファイル内容をJSON配列として $name に渡す |
--rawfile name file | ファイル内容を文字列として $name に渡す |
--args | 以降の引数を $ARGS.positional 配列に渡す |
--jsonargs | 以降の引数をJSONとして $ARGS.positional に渡す |
その他
| オプション | 説明 |
|---|---|
-f file / --from-file file | フィルタをファイルから読み込む |
-L dir | ライブラリのディレクトリを指定 |
--exit-status / -e | false/null なら終了コード 1 |
基本フィルタ
Identity(.)
# 入力をそのまま出力(整形のみ)
echo '{"name":"Alice"}' | jq '.'
フィールドアクセス
# トップレベルフィールド
jq '.name' data.json
# ネストしたフィールド
jq '.address.city' data.json
# 存在しないフィールド(nullを返す、エラーにならない)
jq '.missing' data.json # → null
# エラーにしたい場合は .foo! (jq 1.6+)
jq '.missing!' data.json # エラー
# オプショナルアクセス(エラーを抑制)
jq '.foo??' data.json
配列アクセス
# インデックスでアクセス(0始まり)
jq '.[0]' array.json
# 最後の要素
jq '.[-1]' array.json
# スライス(2番目から4番目)
jq '.[2:4]' array.json
# 配列の全要素を展開(イテレータ)
jq '.[]' array.json
# 長さを取得
jq 'length' array.json
jq '.items | length' data.json
パイプ(|)
# フィルタを繋げる
jq '.users | .[0] | .name' data.json
# 配列展開してから各要素を処理
jq '.users[] | .name' data.json
カンマ(複数出力)
# 複数の値を順に出力
jq '.name, .age' data.json
# 配列として出力したい場合は [] で囲む
jq '[.name, .age]' data.json
オブジェクト構築
# 新しいオブジェクトを作る
jq '{name: .name, age: .age}' data.json
# キー名を動的に指定
jq '{(.key): .value}' data.json
# 既存フィールドを展開して追加
jq '. + {extra: "value"}' data.json
型と値の操作
型確認
# 型を取得("null" "boolean" "number" "string" "array" "object")
jq 'type' data.json
jq '.value | type' data.json
型変換
# 文字列 → 数値
jq '"42" | tonumber' <<< 'null'
# 数値 → 文字列
jq '42 | tostring' <<< 'null'
# 文字列 → JSON(パース)
jq '"[1,2,3]" | fromjson' <<< 'null'
# JSON → 文字列(シリアライズ)
jq '[1,2,3] | tojson' <<< 'null'
# 文字列 → 数値(小数点以下切り捨て)
jq '"3.14" | tonumber | floor' <<< 'null'
null の扱い
# null かどうか確認
jq '. == null' data.json
# null の場合にデフォルト値を使う(// 演算子)
jq '.name // "unknown"' data.json
jq '.count // 0' data.json
# null を除外
jq '[.[] | select(. != null)]' data.json
配列操作
変換・フィルタ
# map:各要素に処理を適用
jq 'map(.name)' users.json
jq 'map(. * 2)' numbers.json
# map_values:オブジェクトの各値に処理を適用
jq 'map_values(. + 1)' obj.json
# select:条件にマッチする要素だけ残す
jq '[.[] | select(.age > 20)]' users.json
jq '[.[] | select(.status == "active")]' users.json
# map と select の組み合わせ
jq 'map(select(.age > 20))' users.json # map + select の慣用形
# reject(条件不一致を残す)
jq '[.[] | select(.age <= 20)]' users.json
ソート・重複除去
# ソート(数値・文字列どちらも)
jq 'sort' numbers.json
jq 'sort_by(.age)' users.json
jq 'sort_by(.name) | reverse' users.json
# 重複除去
jq 'unique' array.json
jq 'unique_by(.name)' users.json
# グループ化
jq 'group_by(.department)' users.json
集合演算
# 配列の結合(flatten しない)
jq '[1,2] + [3,4]' <<< 'null'
# 差集合(含まない要素)
jq '[1,2,3,4] - [2,4]' <<< 'null'
# → [1, 3]
# フラット化(ネストを展開)
jq 'flatten' nested.json
jq 'flatten(1)' nested.json # 1段階だけ展開
# 集計
jq 'add' numbers.json # 合計(配列の + 演算を繰り返す)
jq 'add / length' numbers.json # 平均
jq 'min' numbers.json
jq 'max' numbers.json
jq 'min_by(.age)' users.json
jq 'max_by(.age)' users.json
インデックス・検索
# 要素のインデックスを取得
jq 'index(2)' <<< '[1,2,3]' # → 1
jq 'rindex(2)' <<< '[1,2,1,2]' # → 3(後ろから)
# 含まれるか確認
jq '. | contains([2])' <<< '[1,2,3]' # → true
jq 'any(. > 2)' <<< '[1,2,3]' # → true
jq 'all(. > 0)' <<< '[1,2,3]' # → true
# inside(逆方向のcontains)
jq '[1,2] | inside([1,2,3])' <<< 'null' # → true
オブジェクト操作
# キー一覧を取得
jq 'keys' obj.json
jq 'keys_unsorted' obj.json # 元の順序を保持
# 値一覧を取得
jq 'values' obj.json
# キーと値のペアを配列に
jq 'to_entries' obj.json
# → [{"key":"name","value":"Alice"},...]
# キーと値のペアからオブジェクトに
jq 'from_entries' pairs.json
# to_entries → 加工 → from_entries のパターン
jq 'to_entries | map(.value += "_suffix") | from_entries' obj.json
# フィールドを追加・上書き
jq '. + {"newKey": "newValue"}' obj.json
# フィールドを更新(|=)
jq '.name |= "Bob"' obj.json
jq '.count |= . + 1' obj.json
# フィールドを削除
jq 'del(.name)' obj.json
jq 'del(.a, .b)' obj.json
# 特定キーだけ残す
jq '{name, age}' user.json # .name と .age だけのオブジェクト
# オブジェクトのマージ(後者が優先)
jq '. * {"extra": true}' obj.json
条件分岐
if-then-else
# 基本の if-then-else
jq 'if .age > 18 then "adult" else "minor" end' user.json
# elif も使える
jq '
if .score >= 90 then "A"
elif .score >= 80 then "B"
elif .score >= 70 then "C"
else "F"
end
' score.json
# 条件に応じてフィールドを追加
jq 'if .active then . + {label: "active"} else . end' user.json
try-catch
# エラーを捕捉
jq 'try .foo catch "error occurred"' data.json
# try のみ(エラー時は出力しない)
jq '.[] | try .name' data.json
# optional operator(? は try . と同等)
jq '.foo?' data.json
# エラーを無視して続行
jq '[.[] | .name?]' data.json
文字列操作
# 文字列補間
jq '"Hello, \(.name)!"' user.json
jq '"Count: \(.items | length)"' data.json
# 文字列の分割
jq '"a,b,c" | split(",")' <<< 'null'
# → ["a","b","c"]
# 配列を文字列に結合
jq '["a","b","c"] | join(",")' <<< 'null'
# → "a,b,c"
# 文字列の長さ
jq '.name | length' user.json
# 文字列の切り出し
jq '"hello" | .[1:3]' <<< 'null' # → "el"
# 大文字・小文字変換
jq '.name | ascii_downcase' user.json
jq '.name | ascii_upcase' user.json
# 前後の空白を削除
jq '.name | ltrimstr(" ") | rtrimstr(" ")' user.json
# 特定文字列で始まる・終わるか確認
jq '.name | startswith("Al")' user.json
jq '.name | endswith("ce")' user.json
# 含むか確認
jq '.name | contains("lic")' user.json
# 正規表現マッチ
jq '.email | test("@")' user.json # true/false
jq '.email | match("([^@]+)@(.+)")' user.json # マッチ詳細
jq '.email | capture("(?P<user>[^@]+)@(?P<domain>.+)")' user.json # 名前付きキャプチャ
# 正規表現で抽出
jq '[.text | scan("[0-9]+")]' data.json
# 正規表現で置換
jq '.text | gsub("ERROR"; "WARNING")' data.json
jq '.text | sub("^\\s+"; "")' data.json # 先頭の空白削除
数値演算
# 四則演算
jq '.price * .quantity' item.json
jq '.total / .count' stats.json
jq '.value % 3' data.json
# 数学関数
jq '.x | sqrt' data.json
jq '.x | floor' data.json # 切り捨て
jq '.x | ceil' data.json # 切り上げ
jq '.x | round' data.json # 四捨五入
jq '.x | fabs' data.json # 絶対値
jq '.x | log' data.json # 自然対数
jq '.x | pow(.; 2)' data.json # 累乗
jq '[1,2,3] | add' <<< 'null' # 合計
# 無限大・NaN
jq 'infinite' <<< 'null' # → 1.7976931348623157e+308
jq 'nan' <<< 'null'
jq '1 | isnan' <<< 'null' # → false
jq 'infinite | isinfinite' <<< 'null' # → true
変数・関数定義
変数
# as で変数に代入
jq '.[] | . as $item | "\($item.name): \($item.age)"' users.json
# 複数の変数
jq '
.total as $total |
.items[] |
{name: .name, ratio: (.price / $total)}
' data.json
関数定義
# def でカスタム関数を定義
jq '
def double: . * 2;
[.[] | double]
' numbers.json
# 引数付き関数
jq '
def add_field(name; value): . + {(name): value};
.[] | add_field("status"; "active")
' users.json
# 再帰関数
jq '
def deep_count:
if type == "array" or type == "object"
then [.[] | deep_count] | add // 0
else 1
end;
deep_count
' nested.json
再帰処理(.. と recurse)
# .. ですべてのノードを再帰的に展開
jq '.. | numbers' data.json # 全数値を抽出
jq '.. | strings' data.json # 全文字列を抽出
jq '.. | objects | .name?' data.json # name フィールドを持つ全オブジェクトから抽出
# recurse で条件付き再帰
jq 'recurse(.children?; . != null) | .name' tree.json
# path で値へのパスを取得
jq 'path(.. | numbers)' data.json
# getpath / setpath / delpaths
jq 'getpath(["user","name"])' data.json
jq 'setpath(["user","name"]; "Bob")' data.json
jq 'delpaths([["user","age"]])' data.json
reduce と foreach
reduce
# 配列を1つの値に畳み込む
jq 'reduce .[] as $x (0; . + $x)' numbers.json # 合計
jq 'reduce .[] as $x (1; . * $x)' numbers.json # 積
# オブジェクトを構築しながら集計
jq '
reduce .[] as $item (
{};
. + {($item.key): $item.value}
)
' pairs.json
# 最大値を求める
jq 'reduce .[] as $x (null; if . == null or $x > . then $x else . end)' numbers.json
foreach
# 中間状態も出力する reduce
jq '[foreach .[] as $x (0; . + $x)]' numbers.json
# → [1, 3, 6, 10, ...] (累積和)
–arg / –argjson でシェル変数を渡す
# --arg:文字列として渡す
NAME="Alice"
jq --arg name "$NAME" '.[] | select(.name == $name)' users.json
# --argjson:JSON値として渡す
THRESHOLD=25
jq --argjson threshold "$THRESHOLD" '.[] | select(.age > $threshold)' users.json
# 複数の変数を渡す
jq --arg status "active" --argjson limit 10 \
'[.[] | select(.status == $status)] | .[0:$limit]' users.json
# シェル変数でフィールド名を動的指定
FIELD="name"
jq --arg field "$FIELD" '.[$field]' user.json
# --slurpfile:ファイル内容を変数に
jq --slurpfile config config.json '.[] | select(.id == $config[0].targetId)' data.json
# --rawfile:テキストファイルを文字列として
jq --rawfile template template.txt '{message: $template}' <<< 'null'
curl との連携(最重要)
基本パターン
# APIレスポンスを整形
curl -s https://api.github.com/users/octocat | jq '.'
# 特定フィールドを抽出
curl -s https://api.github.com/users/octocat | jq '.name, .company'
# 配列の全要素から抽出
curl -s https://api.github.com/users/octocat/repos | jq '[.[] | .name]'
# -r で引用符なしの文字列として取得
TOKEN=$(curl -s https://auth.example.com/token | jq -r '.access_token')
POST リクエスト
# jq で JSON ボディを組み立てて curl に渡す
jq -n --arg name "Alice" --argjson age 30 \
'{"name": $name, "age": $age}' \
| curl -s -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d @-
# -n(--null-input)で入力なしに JSON を生成
jq -n '{name: "Alice", age: 30}' | curl -s -X POST ... -d @-
ページネーション処理
# 全ページを取得してまとめる(シェルスクリプト例)
page=1
all_items='[]'
while true; do
response=$(curl -s "https://api.example.com/items?page=$page")
items=$(echo "$response" | jq '.items')
count=$(echo "$items" | jq 'length')
[ "$count" -eq 0 ] && break
all_items=$(echo "$all_items $items" | jq -s 'add')
page=$((page + 1))
done
echo "$all_items" | jq '.'
実用パターン集(80超を厳選)
JSON 整形・変換系
# 整形(pretty print)
jq '.' minified.json
# 1行に圧縮(minify)
jq -c '.' pretty.json
# キーをソート
jq -S '.' data.json
# 特定のキーだけ残す
jq '{id, name, email}' user.json
# 特定のキーを削除
jq 'del(.password, .secret)' user.json
# ネストしたフィールドを平坦化
jq '{name: .name, city: .address.city, zip: .address.zip}' user.json
# 配列をオブジェクトに変換(key-value 配列から)
jq 'map({(.name): .value}) | add' pairs.json
# オブジェクトを配列に変換
jq 'to_entries' obj.json
jq '[to_entries[] | "\(.key)=\(.value)"]' obj.json # KEY=VALUE形式
# JSONをCSVに変換
jq -r '.[] | [.id, .name, .email] | @csv' users.json
# JSONをTSVに変換
jq -r '.[] | [.id, .name, .email] | @tsv' users.json
API レスポンス加工系
# GitHub API:リポジトリ名と星の数を取得
curl -s "https://api.github.com/users/octocat/repos" \
| jq '[.[] | {name: .name, stars: .stargazers_count}] | sort_by(-.stars)'
# GitHub API:フォーク数の多い順にソート
curl -s "https://api.github.com/users/octocat/repos" \
| jq 'sort_by(-.forks_count) | .[0:5] | .[] | .name'
# REST API:ページネーション済みレスポンスからデータを取得
jq '.data.items[] | {id: .id, title: .title}' response.json
# 認証付きAPIリクエスト
curl -s -H "Authorization: Bearer $TOKEN" https://api.example.com/me \
| jq '{id: .id, name: .name}'
# エラーレスポンスの確認
jq 'if .error then error(.error.message) else . end' response.json
# ステータスコードによる分岐
curl -s -w '\n{"status":%{http_code}}' https://api.example.com/data \
| jq -s '.[0] + .[1]'
集計・統計系
# 合計
jq '[.[] | .price] | add' items.json
# 平均
jq '[.[] | .price] | add / length' items.json
# 最大・最小
jq '[.[] | .price] | max, min' items.json
jq 'max_by(.price) | .name' items.json
# カウント(グループ別)
jq 'group_by(.status) | map({status: .[0].status, count: length})' users.json
# 特定条件を満たす要素数
jq '[.[] | select(.active == true)] | length' users.json
# ユニークな値の一覧
jq '[.[] | .department] | unique' users.json
# 合計を key 別に集計
jq '
reduce .[] as $item ({};
.[$item.category] += $item.amount
)
' transactions.json
# パーセンタイル(75th の近似)
jq 'sort | .[length * 3 / 4 | floor]' numbers.json
ログ・設定ファイル加工系
# JSON Lines(NDJSON)を処理(1行1JSON)
jq -r '.message' app.log # 各行の message フィールド
jq 'select(.level == "ERROR")' app.log # ERRORだけフィルタ
# タイムスタンプでフィルタ
jq 'select(.timestamp > "2026-06-01")' events.json
# 特定フィールドの有無でフィルタ
jq 'select(.error != null)' logs.json
jq 'select(has("error"))' logs.json
# ログを整形して表示
jq -r '[.timestamp, .level, .message] | join(" | ")' app.log
# エラーログだけCSVで出力
jq -r 'select(.level == "ERROR") | [.timestamp, .service, .message] | @csv' app.log
# Docker ログ(JSON形式)から取り出す
docker logs mycontainer 2>&1 | jq -R 'fromjson? | select(.level == "error")'
Kubernetes / クラウド系
# kubectl の JSON出力を加工
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
# Running 以外のPodを表示
kubectl get pods -o json \
| jq '.items[] | select(.status.phase != "Running") | .metadata.name'
# デプロイのイメージバージョンを確認
kubectl get deployments -o json \
| jq '.items[] | {name: .metadata.name, image: .spec.template.spec.containers[0].image}'
# AWS CLI の出力を加工
aws ec2 describe-instances \
| jq '.Reservations[].Instances[] | {id: .InstanceId, state: .State.Name, ip: .PrivateIpAddress}'
# 特定タグのインスタンスだけ取得
aws ec2 describe-instances \
| jq '.Reservations[].Instances[]
| select(.Tags[]?.Key == "Environment" and .Tags[]?.Value == "production")
| .InstanceId'
# GCP の gcloud コマンド出力
gcloud compute instances list --format=json \
| jq '.[] | {name: .name, zone: .zone, status: .status}'
package.json / 設定ファイル操作系
# package.json のバージョンを取得
jq -r '.version' package.json
# 依存パッケージ一覧
jq '.dependencies | keys[]' package.json
# スクリプト一覧
jq '.scripts' package.json
# バージョンを更新(ファイル書き換えは sponge か一時ファイル経由)
jq '.version = "2.0.0"' package.json | sponge package.json
# sponge がない場合
jq '.version = "2.0.0"' package.json > tmp.json && mv tmp.json package.json
# 特定の依存を追加
jq '.dependencies["lodash"] = "^4.17.21"' package.json > tmp.json && mv tmp.json package.json
# composer.json / poetry.pyproject.toml でも同様のパターンが使える
jq '.require | to_entries[] | "\(.key): \(.value)"' composer.json
テキスト変換・データ整形系
# CSVのヘッダを使って連想配列に変換
jq -Rn '
(input | split(",")) as $headers |
inputs | split(",") |
[ $headers, . ] | transpose | map({(.[0]): .[1]}) | add
' data.csv
# 配列を特定キーでインデックス化
jq 'INDEX(.[]; .id)' users.json
# → {"1": {id:1, name:...}, "2": {...}}
# 環境変数風の形式に変換
jq -r 'to_entries[] | "\(.key)=\(.value)"' config.json
# 複数JSONファイルをマージ
jq -s '.[0] * .[1]' base.json override.json
# 配列を特定サイズのチャンクに分割
jq '[range(0; length / 3 | ceil) as $i | .[($i*3):(($i+1)*3)]]' <<< '[1,2,3,4,5,6,7]'
# null を除いた配列
jq '[.[] | select(. != null)]' array.json
# 深くネストしたフィールドを安全に取得
jq '.a?.b?.c? // "default"' data.json
シェルスクリプト連携系
# 結果をシェル変数に代入
NAME=$(jq -r '.name' user.json)
echo "Hello, $NAME"
# 複数フィールドを一度に取得(read で受け取る)
read -r NAME AGE EMAIL < <(jq -r '[.name, (.age | tostring), .email] | join(" ")' user.json)
# 配列をシェルの配列に変換
mapfile -t NAMES < <(jq -r '.[] | .name' users.json)
for name in "${NAMES[@]}"; do echo "$name"; done
# jq の結果を xargs に渡す
jq -r '.[] | .url' urls.json | xargs -P 4 curl -s -o /dev/null
# 終了コードでの条件分岐
if jq -e '.active' user.json > /dev/null 2>&1; then
echo "User is active"
fi
# 値の存在確認
jq 'has("name")' user.json # → true/false
スクリプトファイル(-f)
コマンドが長くなったらファイルに保存して管理できます。
# extract_users.jq
# ---------------------
# .users[]
# | select(.active == true)
# | {
# id: .id,
# name: .name,
# email: .email
# }
# ---------------------
jq -f extract_users.jq data.json
関数ライブラリとしても利用できます:
# lib/utils.jq
def is_adult: .age >= 18;
def full_name: "\(.firstName) \(.lastName)";
def mask_email: gsub("(?<=.).(?=.*@)"; "*");
# 使う側
jq -L ./lib -f process.jq data.json
パフォーマンス Tips
--stream で巨大JSONを処理
# 通常の処理(メモリにすべて展開)
jq '.items[]' huge.json
# --stream でストリーミング処理(メモリ効率が高い)
jq -n --stream 'fromstream(1|truncate_stream(inputs; 1))' huge.json
早期終了
# 最初にマッチした要素だけ取得
jq 'first(.[] | select(.id == "123"))' data.json
# 最初の N 件
jq '.[:10]' data.json
jq 'limit(10; .[])' data.json
indices で効率的な検索
# 配列内の全インデックスを取得
jq 'indices(1)' <<< '[1,2,1,3,1]' # → [0,2,4]
macOS / 環境差異に関する注意
シングルクォートの問題(Windows Git Bash)
Windowsのbashではシングルクォートが使えない場合があります。
# Windows Git Bash / PowerShell
jq ".name" data.json # ダブルクォート
jq "{name: .name}" data.json
jq のバージョン差異
| 機能 | 対応バージョン |
|---|---|
?//(オプショナル演算子) | 1.6+ |
@base32 | 1.7+ |
@uri エンコード | 1.5+ |
limit/2 | 1.5+ |
$ENV | 1.5+ |
path 式 | 1.5+ |
# バージョン確認
jq --version
環境変数を jq 内で使う
# $ENV でシェル環境変数にアクセス(jq 1.5+)
jq -n '$ENV.HOME'
jq 'select(.env == $ENV.DEPLOY_ENV)' config.json
トラブルシューティング
null が返ってくる
# フィールド名のタイポ
jq '.nmae' user.json # → null(typo)
# 型が違う(配列なのにオブジェクト操作)
jq '.name' '[{"name":"Alice"}]' # → null(配列に直接アクセスしている)
# 正しくは
jq '.[0].name' '[{"name":"Alice"}]'
jq '.[] | .name' '[{"name":"Alice"}]'
parse error が出る
# JSON が壊れている場合は python で確認
python3 -m json.tool data.json
# 改行区切りのJSONを1つとして読もうとしている
# → -s(slurp)か、各行を個別に処理
jq '.' <<< '{"a":1}{"b":2}' # エラー
cat ndjson.txt | jq '.' # 1行ずつ処理される
# 未対応の BOM(バイトオーダーマーク)
file data.json # → UTF-8 BOM の場合は除去
sed -i '1s/^\xEF\xBB\xBF//' data.json
フィルタに特殊文字を含むキーにアクセスしたい
# ハイフンやスペースを含むキー
jq '.["my-key"]' data.json
jq '.["content-type"]' headers.json
# 数字始まりのキー
jq '.["1st"]' data.json
シェル変数をフィルタに埋め込みたい
# ❌ シングルクォートではシェル変数が展開されない
FIELD="name"
jq '.$FIELD' data.json # 動かない
# ✅ --arg を使う
jq --arg field "$FIELD" '.[$field]' data.json
# ✅ またはダブルクォートで書く(エスケープに注意)
jq ".${FIELD}" data.json # 単純なフィールド名なら動くが非推奨
数値精度の問題
# jq は IEEE 754 倍精度浮動小数点を使うため、大きな整数は精度が失われる
jq '.id' <<< '{"id": 99999999999999999}'
# → 100000000000000000(精度が失われる)
# 文字列として扱う回避策
jq -r '.id | tostring' <<< '{"id": 99999999999999999}'
よくある質問(FAQ)
Q1. jq でファイルを直接書き換えるには?
# sponge(moreutils)を使う
jq '.version = "2.0.0"' package.json | sponge package.json
# sponge がない場合は一時ファイル経由
jq '.version = "2.0.0"' package.json > tmp.json && mv tmp.json package.json
# bash のプロセス置換(一部環境では動かない)
jq '.version = "2.0.0"' package.json | tee package.json # ❌ 競合する可能性あり
Q2. -r と -c の違いは?
# -r(raw output):文字列の引用符を外す
jq -r '.name' <<< '{"name":"Alice"}' # → Alice(引用符なし)
jq '.name' <<< '{"name":"Alice"}' # → "Alice"(引用符あり)
# -c(compact):整形せず1行に圧縮(JSON形式は保持)
jq -c '.' <<< '{"name":"Alice","age":30}'
# → {"name":"Alice","age":30}
# 組み合わせも可能
jq -rc '.[] | .name' users.json # 配列の各要素のnameを1行ずつ出力
Q3. map と .[] | の違いは?
# map は配列 → 配列を返す
jq 'map(.name)' users.json # → ["Alice","Bob",...]
# .[] | は各要素を個別に出力する(配列を返さない)
jq '.[] | .name' users.json # → "Alice"\n"Bob"\n...
# 配列で受け取りたいなら [] で囲む
jq '[.[] | .name]' users.json # map と同等
Q4. //(代替演算子)の使い方は?
# null または false のときに右辺を使う
jq '.name // "unknown"' user.json
jq '.count // 0' stats.json
# 注意:false も代替される
jq 'false // "default"' <<< 'null' # → "default"
# null だけ代替したい場合は if を使う
jq 'if .name == null then "unknown" else .name end' user.json
Q5. エラーを無視して処理を続けたい
# ? でエラーを抑制
jq '.[] | .name?' data.json
# try-catch
jq '.[] | try .name catch null' data.json
# フィールドがないオブジェクトをスキップ
jq '[.[] | select(has("name")) | .name]' data.json
Q6. 複数のJSONファイルをマージしたい
# 2つのJSONをマージ(後者が優先)
jq -s '.[0] * .[1]' base.json override.json
# 配列を連結する場合
jq -s '.[0] + .[1]' array1.json array2.json
# 複数ファイルを全部マージ
jq -s 'reduce .[] as $item ({}; . * $item)' *.json
Q7. NDJSON(JSON Lines)を処理したい
# 各行が独立したJSON(改行区切り)
# jq はデフォルトで1行ずつ処理する
jq '.name' users.ndjson
# 全行をまとめて配列に(-s)
jq -s '.' users.ndjson
# 全行を配列にしてから集計
jq -s 'map(select(.age > 20)) | length' users.ndjson
Q8. @base64 @uri @csv などのフォーマット文字列は?
# @base64:Base64エンコード
jq -r '"hello" | @base64' <<< 'null' # → aGVsbG8=
jq -r '"aGVsbG8=" | @base64d' <<< 'null' # → hello
# @uri:URLエンコード
jq -r '"hello world" | @uri' <<< 'null' # → hello%20world
# @html:HTMLエスケープ
jq -r '"<div>" | @html' <<< 'null' # → <div>
# @csv:CSV形式
jq -r '[.id, .name, .email] | @csv' user.json
# @tsv:TSV形式
jq -r '[.id, .name, .email] | @tsv' user.json
# @sh:シェル引数として安全にエスケープ
jq -r '.name | @sh' user.json # → 'Alice'
Q9. jq より新しい・速いツールはありますか?
| ツール | 特徴 |
|---|---|
| gron | JSONをgrep可能な形式に変換 |
| fx | インタラクティブなJSON探索ツール |
| dasel | JSON/YAML/TOML/XML を統一的に操作 |
| yq | jq 互換の YAML 対応版 |
| miller (mlr) | CSV/TSV/JSON 統合処理 |
# gron の例(grep と組み合わせやすい)
gron data.json | grep "name"
# yq で YAML も同じ構文で
yq '.name' config.yaml
Q10. jq フィルタのデバッグ方法は?
# debug で途中の値を確認(stderr に出力)
jq '.users | debug | .[0] | .name' data.json
# stderr に出力しつつ値を通す
jq '.users | (debug | .[0] | .name)' data.json
# 段階的に確認
echo '{"users":[{"name":"Alice"}]}' | jq '.users' # まずここまで
echo '{"users":[{"name":"Alice"}]}' | jq '.users[0]' # 次にここまで
echo '{"users":[{"name":"Alice"}]}' | jq '.users[0].name' # 最後
参考リンク・関連資料
公式ドキュメント
ツール・プレイグラウンド
- jqplay.org – ブラウザでjqを試せるプレイグラウンド
- jq cookbook – 実用レシピ集
代替ツール
関連記事(本サイト)
- Linux grep オプション一覧 – grepコマンドリファレンス
- Linux sed オプション一覧 – sedコマンドリファレンス
- curl オプション一覧 – curlコマンドリファレンス
- Linux find オプション一覧 – findコマンドリファレンス
まとめ
jqコマンドはJSONを扱うエンジニアに必須のツール。要点を再整理します。
- 基本構文:
jq [オプション] フィルタ [ファイル...] - 超頻出フィルタ:
.(整形)、.field(取得)、.[](展開)、|(パイプ)、[](配列構築) - 配列操作:
map・select・sort_by・group_by・unique_by・add - オブジェクト操作:
keys・values・to_entries・from_entries・del・|= - 条件分岐:
if-then-else・try-catch・//(代替演算子)・select - 変数渡し:
--arg(文字列)・--argjson(JSON値)・as $var - 出力制御:
-r(引用符なし)・-c(1行圧縮)・-e(終了コード)・-S(ソート) - curl 連携:
curl -s ... | jq・jq -n '{}'| curl ... -d @- - ファイル書き換え:
spongeか一時ファイル経由(-iは非対応) - 代替ツール:
yq(YAML対応)・gron(grep連携)・fx(インタラクティブ)
grep・sed・jq の3本柱を使いこなせれば、テキスト・設定ファイル・APIレスポンスのほぼすべてをコマンドラインで処理できるようになります。
本記事は2026年6月時点の情報をもとに、jq 1.7.x(Ubuntu 24.04)、jq 1.7.x(macOS Homebrew)での動作確認に基づき作成しています。バージョンによってオプション挙動が異なる場合があるため、最新の情報は公式マニュアルもあわせてご確認ください。
-
前の記事
【完全版】crontabの書き方と実用例まとめ|Linux定期実行の設定方法を徹底解説 2026.06.18
-
次の記事
Linux「command not found」エラーの原因と解決方法|PATH・シェル設定を徹底解説 2026.06.19
コメントを書く