jq 是一個輕量級的命令列 JSON 處理器,用來:
- 格式化 JSON 輸出
- 提取特定欄位
- 過濾和轉換 JSON 資料
- 在 shell 腳本中處理 API 回應
官網:https://jqlang.github.io/jq/
brew install jq
jq --version
jq [選項] '過濾器' [檔案]
jq '.' data.json
echo '{"name":"Alice"}' | jq '.'
curl https://api.example.com | jq '.'
| 選項 |
說明 |
範例 |
. |
原樣輸出(格式化) |
jq '.' |
-r |
原始輸出(去除引號) |
jq -r '.name' |
-c |
緊湊輸出(單行) |
jq -c '.' |
-S |
排序 key |
jq -S '.' |
-e |
設定退出碼 |
jq -e '.error' |
-n |
不讀取輸入 |
jq -n '{a:1}' |
echo '{"name":"Alice","age":30,"city":"Taipei"}' > user.json
| 操作 |
語法 |
範例 |
輸出 |
| 格式化 |
. |
jq '.' user.json |
美化的 JSON |
| 取得欄位 |
.key |
jq '.name' user.json |
"Alice" |
| 去除引號 |
-r .key |
jq -r '.name' user.json |
Alice |
| 多層存取 |
.key.subkey |
jq '.address.city' |
取得巢狀值 |
| 可選存取 |
.key? |
jq '.missing?' |
不存在時不報錯 |
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' > users.json
| 操作 |
語法 |
範例 |
輸出 |
| 第一個元素 |
.[0] |
jq '.[0]' users.json |
{"name":"Alice",...} |
| 最後一個 |
.[-1] |
jq '.[-1]' users.json |
最後一個元素 |
| 切片 |
.[start:end] |
jq '.[0:2]' |
前兩個元素 |
| 所有元素 |
.[] |
jq '.[]' users.json |
展開陣列 |
| 陣列長度 |
length |
jq 'length' users.json |
2 |
| 取得欄位 |
.[].key |
jq '.[].name' users.json |
"Alice" "Bob" |
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25},{"name":"Charlie","age":35}]' > users.json
| 操作 |
說明 |
範例 |
| 過濾條件 |
選擇 age > 28 |
`jq '.[] |
| 判斷相等 |
選擇 name 為 Alice |
`jq '.[] |
| 包含字串 |
name 包含 "li" |
`jq '.[] |
| 多條件 AND |
25 < age < 35 |
`jq '.[] |
| 多條件 OR |
age < 25 或 > 35 |
`jq '.[] |
| 存在判斷 |
有 email 欄位 |
`jq '.[] |
| 操作 |
語法 |
範例 |
輸出 |
| 取多個欄位 |
{key1, key2} |
jq '{name, age}' user.json |
{"name":"Alice","age":30} |
| 重新命名 |
{newKey: .oldKey} |
jq '{username: .name}' user.json |
{"username":"Alice"} |
| 建構物件 |
{key: value} |
jq '{name: .name, adult: (.age >= 18)}' |
建構新物件 |
| 建構陣列 |
[items] |
jq '[.name, .age]' user.json |
["Alice", 30] |
| Map 轉換 |
map(expression) |
jq 'map(.name)' users.json |
["Alice","Bob"] |
| 增加欄位 |
. + {key: value} |
jq '. + {country: "TW"}' |
新增欄位 |
| 操作 |
說明 |
範例 |
| 長度 |
陣列長度 |
`jq '.users |
| 鍵列表 |
取得所有 key |
jq 'keys' user.json |
| 值列表 |
取得所有值 |
`jq '.[] |
| 最小值 |
最小年齡 |
`jq '[.[].age] |
| 最大值 |
最大年齡 |
`jq '[.[].age] |
| 加總 |
年齡總和 |
`jq '[.[].age] |
| 平均 |
平均年齡 |
`jq '[.[].age] |
| 排序 |
排序陣列 |
jq 'sort' array.json |
| 排序(依欄位) |
依 age 排序 |
jq 'sort_by(.age)' users.json |
| 反轉 |
反轉陣列 |
jq 'reverse' array.json |
| 唯一值 |
去重複 |
jq 'unique' array.json |
| 分組 |
依 age 分組 |
jq 'group_by(.age)' |
| 操作 |
說明 |
範例 |
| 字串連接 |
連接字串 |
jq '.firstName + " " + .lastName' |
| 轉大寫 |
轉大寫 |
`jq '.name |
| 轉小寫 |
轉小寫 |
`jq '.name |
| 分割 |
分割字串 |
`jq '.email |
| 測試正則 |
測試是否符合 |
`jq '.email |
| 匹配正則 |
提取匹配內容 |
`jq '.text |
| 替換 |
替換第一個 |
`jq '.name |
| 替換所有 |
替換所有 |
`jq '.text |
| 包含 |
包含判斷 |
`jq '.name |
| 開頭 |
開頭判斷 |
`jq '.name |
| 結尾 |
結尾判斷 |
`jq '.name |
| 操作 |
說明 |
範例 |
| 轉字串 |
數字轉字串 |
`jq '.age |
| 轉數字 |
字串轉數字 |
`jq '.ageStr |
| 轉陣列 |
包成陣列 |
jq '[.name, .age]' |
| 型別檢查 |
查看型別 |
`jq '.age |
| 操作 |
範例 |
| if-then-else |
jq 'if .age >= 18 then "adult" else "minor" end' |
| 三元運算 |
`jq '.age >= 18 |
| 空值處理 |
jq '.email // "no-email"' |
| 操作 |
說明 |
範例 |
| 管道 |
串接多個操作 |
`jq '.users |
| 逗號 |
產生多個輸出 |
jq '.name, .age' |
| 括號 |
調整優先順序 |
jq '(.age + 5) * 2' |
curl -s https://api.github.com/users/octocat/repos | jq '.[].name'
curl -s https://api.github.com/users/octocat/repos | \
jq '.[:5] | .[] | {name: .name, stars: .stargazers_count}'
docker ps --format json | jq -r '.Names'
docker ps -a --format json | jq 'select(.Image | contains("nginx"))'
kubectl get pods -o json | jq -r '.items[].metadata.name'
kubectl get pods -n default -o json | \
jq -r '.items[] | "\(.metadata.name): \(.status.podIP)"'
kubectl get pods -o json | \
jq '.items[] | select(.status.phase == "Running") | .metadata.name'
cat << 'EOF' > data.json
{
"users": [
{
"name": "Alice",
"contacts": {
"email": "alice@example.com",
"phone": "123-456"
}
},
{
"name": "Bob",
"contacts": {
"email": "bob@example.com"
}
}
]
}
EOF
jq '.users[].contacts.email' data.json
jq '.users[] | select(has("contacts") and (.contacts | has("phone")))' data.json
echo '[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]' | \
jq 'map({user_id: .id, username: .name})'
cat << 'EOF' > orders.json
[
{"product": "A", "price": 100, "quantity": 2},
{"product": "B", "price": 50, "quantity": 5},
{"product": "A", "price": 100, "quantity": 1}
]
EOF
jq '[.[] | .price * .quantity] | add' orders.json
jq 'group_by(.product)' orders.json
jq 'group_by(.product) | map({product: .[0].product, total: map(.quantity) | add})' orders.json
cat << 'EOF' > products.json
[
{"name": "Laptop", "price": 50000, "stock": 5, "category": "electronics"},
{"name": "Mouse", "price": 500, "stock": 0, "category": "electronics"},
{"name": "Book", "price": 300, "stock": 10, "category": "books"}
]
EOF
jq '.[] | select(.category == "electronics" and .stock > 0 and .price < 1000)' products.json
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' | \
jq -r '.[] | [.name, .age] | @csv'
echo '[{"name":"Alice","age":30},{"name":"Bob","age":25}]' | \
jq -r '["name","age"], (.[] | [.name, .age]) | @csv'
export USERNAME="Alice"
jq -n --arg name "$USERNAME" '{user: $name, timestamp: now}'
jq -s '.' file1.json file2.json
jq -s 'map(.name)' file1.json file2.json
curl -s https://api.example.com | jq -r '.data[] | .name'
jq '[.[] | select(.age > 25)] | sort_by(.age) | .[0:5]' users.json
jq -r '.[] | "\(.name)\t\(.age)\t\(.city)"' users.json
jq '.[] | {name, status: (if .age >= 18 then "adult" else "minor" end)}' users.json
jq -e '.error != null' response.json && echo "有錯誤"
cat messy.json | jq '.' > pretty.json
jq '.field | type' data.json
jq '.name' data.json
jq -r '.name' data.json
jq '.missing_field' data.json
jq '.missing_field?' data.json
head -n 5 large.json | jq '.[] | select(.status == "active")'
jq '.[] | select(.status == "active")' large.json
jq '.' data.json | wc -l
jq -c '.' data.json | wc -l
jq '.' data.json
jq '.[] | select(.age > 25)' data.json
jq '.[] | select(.age > 25) | {name, age}' data.json
jq '.items[] | select(.price > 100) | {name: .name, discount: (.price * 0.1)}' data.json
jq '.items[] | select(.price > 100) | . as $item | {name: $item.name, discount: ($item.price * 0.1)}' data.json
if jq -e '.error' response.json > /dev/null 2>&1; then
echo "API 回應包含錯誤"
jq -r '.error.message' response.json
else
echo "API 回應正常"
jq -r '.data' response.json
fi
name=$(jq -r '.name' data.json)
age=$(jq -r '.age' data.json)
city=$(jq -r '.city' data.json)
read name age city < <(jq -r '.name, .age, .city' data.json)
jq '.' data.json
jq -r '.name' data.json
jq -r '.[].name' data.json
jq '.[] | select(.age > 25)' data.json
jq '{username: .name, years: .age}' data.json
jq '.name' user.json
jq -r '.name' user.json
jq .users | .[0] data.json
jq '.users | .[0]' data.json
jq '.[]' users.json | grep name
jq -r '.[].name' users.json | grep Alice
| 需求 |
語法 |
| 格式化 |
jq '.' |
| 取欄位 |
jq -r '.field' |
| 取陣列元素 |
jq '.[0]' 或 jq '.[]' |
| 過濾 |
jq '.[] | select(.age > 25)' |
| 轉換 |
jq '.[] | {new: .old}' |
| 排序 |
jq 'sort_by(.field)' |
| 長度 |
jq 'length' |
| 加總 |
jq 'map(.price) | add' |
核心概念:
. = 目前位置
| = 管道傳遞
[] = 陣列展開
select() = 過濾
map() = 轉換每個元素
建議:開始時只用 .、.field、.[]、select(),熟練後再用進階功能。
建立日期:2025-10-15
最後更新:2025-11-18