3. JSON va YAML — jq, yq
🎯 Bu bobda nimani o'rganasiz:
jqasoslari — identity, field access, array operatsiyalari- Filter va transform —
select,map,group_by,sort_by- Object yaratish —
{name: .a, age: .b}- String va son operatsiyalari
curl + jq— eng kuchli pipeline (har DevOps kunlik vositasi)yq— YAML uchun bir xil sintaksis- Real misollar — GitHub API, AWS, Kubernetes
⏱ Vaqt: ~35 daqiqa 🧪 Mashqlar:
bashlings watch 13_jq(kelajak sprint)
3.1. Nima uchun jq kerak?
DevOps va SRE ish kunining 60-70%i — JSON. API javoblari, Kubernetes manifestlari, AWS CLI chiqishi, Docker inspect, GitHub Actions output. Hammasi JSON.
Bashda JSON'ni grep yoki awk bilan parse qilish — xavfli va xato:
# ❌ XAVFLI — qator tartibi yoki escape o'zgarsa singadi
curl -s api.com/user | grep '"name"' | cut -d'"' -f4jq — JSON uchun yaratilgan, JSON tushunadigan vosita. Strukturani anglaydi, regex'ga umid bermaydi.
# ✓ TO'G'RI — strukturali
curl -s api.com/user | jq -r '.name'Asosiy g'oya
JSON bilan ishlasangiz — jq ishlating. Hech qachon grep/awk bilan JSON parse qilmang.
3.2. O'rnatish
# macOS
brew install jq
# Ubuntu / Debian
sudo apt install jq
# Alpine
apk add jq
# Statik binary (har joyda)
curl -L https://github.com/jqlang/jq/releases/latest/download/jq-linux-amd64 -o /usr/local/bin/jq
chmod +x /usr/local/bin/jq
# Versiya tekshirish
jq --version
# jq-1.7.13.3. Identity filter va pretty-print
Eng oddiy — identity filter .:
echo '{"name":"Ali","age":25}' | jq '.'Natija (pretty-formatted, ranglangan):
{
"name": "Ali",
"age": 25
}Asosiy flaglar
| Flag | Mazmuni |
|---|---|
-r | Raw — string'lardan qo'shtirnoq olib tashlash |
-c | Compact — bir qatorda |
-s | Slurp — barcha inputni bitta array deb o'qish |
-n | Null input (jq generatsiya qiladi) |
-e | Exit code (null yoki false chiqsa → 1) |
-S | Sort keys |
-a | ASCII-only output (escape unicode) |
--tab | Tab bilan indent |
# Raw (qo'shtirnoqsiz)
echo '"hello"' | jq '.' # "hello"
echo '"hello"' | jq -r '.' # hello
# Compact
echo '{"a":1,"b":2}' | jq -c '.'
# {"a":1,"b":2}-r har doim shellda ishlatish uchun
Agar jq natijasini shell o'zgaruvchisiga yozasiz, -r majburiy. Aks holda "qo'shtirnoq" ichida saqlanadi.
name=$(echo '{"name":"Ali"}' | jq '.name')
echo "$name" # "Ali" ← qo'shtirnoq qoldi
name=$(echo '{"name":"Ali"}' | jq -r '.name')
echo "$name" # Ali ← toza3.4. Field access
Sodda field
echo '{"name":"Ali","age":25,"city":"Toshkent"}' | jq -r '.name'
# Ali
echo '{"name":"Ali","age":25}' | jq '.age'
# 25Nested field
echo '{"user":{"email":"ali@example.com","verified":true}}' | jq -r '.user.email'
# ali@example.comBracket notation (maxsus belgilar uchun)
# Kalit ichida bo'shliq, raqamlar yoki tire bo'lsa
echo '{"user-id":42}' | jq '.["user-id"]'
# 42Optional access — ?
# Maydon bo'lmasa — null (xato emas)
echo '{"name":"Ali"}' | jq '.email?'
# null
# Tirnoqsiz access:
echo '{"name":"Ali"}' | jq '.email'
# null
# Lekin agar input string yoki array bo'lsa, .field xato beradi —
# `.field?` "silent fail" qiladi:
echo '"just a string"' | jq '.email?' # null (xato emas)
echo '"just a string"' | jq '.email' # ERROR3.5. Array operatsiyalari
# Misol input:
data='[10, 20, 30, 40, 50]'Indeks bo'yicha
echo "$data" | jq '.[0]' # 10
echo "$data" | jq '.[-1]' # 50 (oxirgi)
echo "$data" | jq '.[2]' # 30Slice — .[start:end]
echo "$data" | jq '.[1:3]' # [20, 30] (1..2 indekslar)
echo "$data" | jq '.[:2]' # [10, 20] (boshidan 2 ta)
echo "$data" | jq '.[-2:]' # [40, 50] (oxirgi 2 ta)Iteratsiya — .[]
echo "$data" | jq '.[]'
# 10
# 20
# 30
# 40
# 50.[] — har elementni alohida (multi-output).
Hajm — length
echo "$data" | jq 'length' # 5
echo '{"a":1,"b":2,"c":3}' | jq 'length' # 3 (object keys soni)
echo '"hello"' | jq 'length' # 5 (belgi soni)Object'lar massivi
users='[
{"name":"Ali","age":25},
{"name":"Vali","age":30},
{"name":"Gulnora","age":28}
]'
# Hammasini chiqarish
echo "$users" | jq '.[]'
# Faqat ismlar
echo "$users" | jq -r '.[].name'
# Ali
# Vali
# Gulnora
# Faqat 2-element ismi
echo "$users" | jq -r '.[1].name' # Vali3.6. Pipe | ichida zanjirlash
jq ichida | — bashning | bilan o'xshash, lekin filter'lar zanjiri.
echo "$users" | jq '.[] | .name'
# Ali
# Vali
# Gulnora
echo "$users" | jq '.[] | .name | ascii_upcase'
# ALI
# VALI
# GULNORA| chap natijani o'ng tomonga uzatadi — xuddi shell pipe kabi.
3.7. Filter — select(...)
select(condition) — shartga mos kelganlarini qoldiradi.
echo "$users" | jq '.[] | select(.age >= 28)'
# {"name":"Vali","age":30}
# {"name":"Gulnora","age":28}
echo "$users" | jq -r '.[] | select(.age >= 28) | .name'
# Vali
# GulnoraOperatorlar
| Operator | Misol |
|---|---|
== | .age == 25 |
!= | .status != "deleted" |
>, < | .score > 80 |
>=, <= | .age >= 18 |
and | .age > 18 and .verified |
or | .role == "admin" or .role == "owner" |
not | `.deleted |
Mavjudligini tekshirish
# Maydon mavjudmi?
echo '{"a":1}' | jq 'has("a")' # true
echo '{"a":1}' | jq 'has("b")' # false
# String yoki array elementi
echo '"hello world"' | jq 'contains("world")' # true
echo '[1,2,3]' | jq 'contains([2])' # true3.8. map(...) — transform
map(f) — [ .[] | f ] ning qisqartmasi.
# Har yoshga 1 qo'shish
echo "$users" | jq 'map(.age + 1)'
# [26, 31, 29]
# Object'larni transform qilish
echo "$users" | jq 'map({ism: .name, yosh: .age})'
# [
# {"ism":"Ali","yosh":25},
# ...
# ]3.9. Object yaratish
# Yangi object yasash
echo '{"firstName":"Ali","lastName":"Karim"}' | jq '{
fullName: (.firstName + " " + .lastName),
initials: (.firstName[0:1] + .lastName[0:1])
}'
# {
# "fullName": "Ali Karim",
# "initials": "AK"
# }to_entries va from_entries
Object'ni key-value pairs massiviga aylantirish:
echo '{"name":"Ali","age":25}' | jq 'to_entries'
# [
# {"key":"name","value":"Ali"},
# {"key":"age","value":25}
# ]
# Teskari:
echo '[{"key":"a","value":1},{"key":"b","value":2}]' | jq 'from_entries'
# {"a":1,"b":2}Foydali pattern — har value'ni transform qilish:
# Har qiymatni stringga aylantirish
echo '{"a":1,"b":2}' | jq 'with_entries(.value |= tostring)'
# {"a":"1","b":"2"}3.10. group_by, sort_by, unique_by
people='[
{"name":"Ali","dept":"IT","age":25},
{"name":"Vali","dept":"HR","age":30},
{"name":"Gulnora","dept":"IT","age":28},
{"name":"Bobur","dept":"HR","age":35}
]'
# Bo'lim bo'yicha guruhlash
echo "$people" | jq 'group_by(.dept)'
# Yosh bo'yicha tartiblash
echo "$people" | jq 'sort_by(.age) | .[].name'
# "Ali"
# "Gulnora"
# "Vali"
# "Bobur"
# Teskari
echo "$people" | jq 'sort_by(.age) | reverse | .[].name'
# Unique
echo "$people" | jq 'unique_by(.dept) | .[].dept'
# "HR"
# "IT"Bo'lim bo'yicha hisoblash
echo "$people" | jq 'group_by(.dept) | map({
dept: .[0].dept,
count: length,
avg_age: (map(.age) | add / length)
})'
# [
# {"dept":"HR","count":2,"avg_age":32.5},
# {"dept":"IT","count":2,"avg_age":26.5}
# ]3.11. String va son operatsiyalari
Stringlar
| Funksiya | Misol |
|---|---|
ascii_upcase | `"hello" |
ascii_downcase | `"HELLO" |
length | `"hello" |
split(",") | `"a,b,c" |
join("-") | `["a","b"] |
gsub("re"; "x") | Global regex replace |
sub("re"; "x") | Birinchi regex moslash |
ltrimstr("pre") | Prefix olib tashlash |
rtrimstr(".log") | Suffix olib tashlash |
tostring | Number → string |
tonumber | String → number |
echo '"hello world"' | jq -r 'ascii_upcase'
# HELLO WORLD
echo '["a","b","c"]' | jq -r 'join(",")'
# a,b,c
echo '"app-prod-v2.tar.gz"' | jq -r 'ltrimstr("app-") | rtrimstr(".tar.gz")'
# prod-v2Sonlar
| Funksiya | Mazmuni |
|---|---|
add | Array yig'indi |
min, max | Eng kichik / katta |
floor, ceil | Yaxlitlash |
fabs | Absolyut qiymat |
echo '[10,20,30,40]' | jq 'add' # 100
echo '[10,20,30,40]' | jq 'min' # 10
echo '[10,20,30,40]' | jq 'max' # 40
echo '[1.4,2.6]' | jq 'map(floor)' # [1, 2]3.12. curl + jq — eng kuchli pipeline
Top 5 GitHub repositoriya'lari (yulduzlar)
curl -s "https://api.github.com/search/repositories?q=language:rust&sort=stars" \
| jq -r '.items[:5] | .[] | "\(.stargazers_count) \(.full_name)"'
# 96234 rust-lang/rust
# 78912 denoland/deno
# ...GitHub foydalanuvchi haqida ma'lumot
curl -s https://api.github.com/users/torvalds | jq '{
name: .name,
bio: .bio,
repos: .public_repos,
followers: .followers
}'
# {
# "name": "Linus Torvalds",
# "bio": null,
# "repos": 6,
# "followers": 235000
# }Bitta maydonni shell o'zgaruvchiga
STARS=$(curl -s https://api.github.com/repos/rust-lang/rust | jq '.stargazers_count')
echo "Rust starlari: $STARS"Filter + transform
# Faqat ochiq issue'lar, eng so'nggi 5 tasi
curl -s "https://api.github.com/repos/cli/cli/issues?state=open" \
| jq -r '.[:5] | .[] | "[\(.number)] \(.title) — \(.user.login)"'Multi-source — jq -s (slurp)
Bir nechta JSON inputni bitta array qilib o'qish:
curl -s api1.com > a.json
curl -s api2.com > b.json
jq -s '.[0] + .[1]' a.json b.json
# Ikkalasini birlashtirish3.13. Conditionals — if-then-else-end
echo '{"age":17}' | jq 'if .age >= 18 then "kattalar" else "yoshlar" end'
# "yoshlar"
echo '{"age":25}' | jq 'if .age >= 18 then "kattalar" else "yoshlar" end'
# "kattalar"elif ham bor:
echo '{"score":85}' | jq '
if .score >= 90 then "A"
elif .score >= 70 then "B"
elif .score >= 50 then "C"
else "F"
end
'
# "B"3.14. yq — YAML uchun
yq (Mike Farah versiyasi, Go'da yozilgan) — jq bilan bir xil sintaksis YAML uchun.
# O'rnatish
brew install yq # macOS
sudo snap install yq # Ubuntu
# Versiya
yq --versionKubernetes manifest o'qish
cat deployment.yaml | yq '.spec.replicas'
# 3
# Konteyner image'ini ko'rish
yq '.spec.template.spec.containers[0].image' deployment.yaml
# nginx:1.21Qiymatni o'zgartirish (in-place)
# replicas ni 5 ga
yq -i '.spec.replicas = 5' deployment.yaml
# Tag yangilash
yq -i '.spec.template.spec.containers[0].image = "nginx:1.25"' deployment.yamlYAML ↔ JSON konvertatsiya
# YAML → JSON
yq -o=json deployment.yaml > deployment.json
# JSON → YAML
yq -p=json -o=yaml deployment.jsonyq versiyalari farqli
Ikki mashhur yq bor:
- Mike Farah (Go) —
jqsintaksis, bu yerda ko'rsatilgan - Python (kislyuk/yq) —
jqwrapper, sintaksis biroz farqli
yq --version orqali qaysi versiyangiz borligini tekshiring.
3.15. Real production misollar
Misol 1 — AWS EC2 instance'larni filtrlash
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[]
| select(.State.Name == "running")
| "\(.InstanceId) \(.InstanceType) \(.PublicIpAddress)"'
# i-0abc123 t3.medium 54.232.x.x
# i-0def456 t3.large 18.231.x.xMisol 2 — Docker konteyner cleanup
# 1 soatdan ko'p ishlovchi `Exited` konteynerlar
docker ps -a --format '{{json .}}' \
| jq -r 'select(.State == "exited" and (.RunningFor | test("hour"))) | .ID' \
| xargs -r docker rmMisol 3 — Kubernetes Pod statuslari
kubectl get pods -o json \
| jq -r '.items[]
| "\(.metadata.namespace)/\(.metadata.name) — \(.status.phase)"' \
| sort -k2
# default/web-abc — Running
# default/web-def — Pending
# kube-system/coredns — RunningMisol 4 — Log fayl tahlili (JSON log format)
# Apache structured logs
cat access.log | jq -r 'select(.status >= 500) | "\(.timestamp) \(.path) \(.status)"' \
| head -20Misol 5 — Konfiguratsiya backup audit
# Kubernetes deployment image versiyalari
for f in deployments/*.yaml; do
image=$(yq '.spec.template.spec.containers[0].image' "$f")
printf '%-30s %s\n' "$(basename "$f")" "$image"
done3.16. Tez-tez uchraydigan xatolar
Klassik tuzoqlar
-rflagini unutish.bashuser=$(... | jq '.name') # "Ali" — qo'shtirnoq qoldi! user=$(... | jq -r '.name') # Ali — tozanullqiymatlarni handle qilmaslik.bashemail=$(... | jq -r '.email') # agar yo'q bo'lsa "null" qaytaradi (string!) email=$(... | jq -r '.email // empty') # bo'sh stringObject access yo'qida xato.
bash... | jq '.user.email' # user yo'q bo'lsa — XATO ... | jq '.user.email?' # null qaytaradimapichida.[]ishlatish.bashecho '[1,2,3]' | jq 'map(.[])' # XATO echo '[1,2,3]' | jq 'map(. * 2)' # ✓CSV'ga export uchun
@csvunutish.bash... | jq -r '[.name, .age] | @csv' # "Ali",25jqarifmetik darajalik (precision). Katta sonlar IEEE 754 double'ga aylanadi — 16-17 ta raqamdan keyin precision yo'qoladi.Numeric vs string comparison.
bashecho '{"v":"5"}' | jq '.v > 3' # XATO (string vs number) echo '{"v":"5"}' | jq '(.v | tonumber) > 3' # ✓jqnewline'lar bilan tashvish. Multiline string olishingiz mumkin —-c(compact) ishlatib bir qatorga aylantirin.
3.17. Mashqlar
🧪 Kelajakda
bashlings watch 13_jqpaketida.
Foydalanuvchi nomi —
{"user":{"name":"Ali","email":"ali@example.com"}}JSON dan faqat email'nijq -rbilan oling.Filter —
[{"age":15},{"age":20},{"age":17},{"age":30}]dan kattalar (>=18) sonini chiqaring.GitHub stars —
curl -s https://api.github.com/repos/cli/cli | jq -r '.stargazers_count'orqali GitHub CLI ning yulduzlar sonini oling.CSV transform —
[{"name":"Ali","age":25},{"name":"Vali","age":30}]ni CSV ko'rinishida chiqaring (@csvorqali).YAML edit — har qanday
deployment.yamlfaylidareplicasni 3 dan 5 ga in-place (-i) o'zgartiring.
3.18. Xulosa
| Tushuncha | Asosiy nuqta |
|---|---|
jq '.' | Identity, pretty-print |
jq '.field' | Sodda field access |
jq '.user.email' | Nested |
jq '.field?' | Optional access (null-safe) |
jq '.[0]' / jq '.[]' | Array indeks / iteratsiya |
jq 'length' | Hajm |
| `jq '... | select(...)'` |
jq 'map(...)' | Transform |
jq 'group_by(.x)' | Guruhlash |
jq '{a: .b}' | Object yaratish |
jq 'if X then Y else Z end' | Shart |
jq -r | Raw — har shell o'zgaruvchisida majburiy |
jq -c | Compact bir qator |
jq -s | Slurp — barcha inputni array deb o'qish |
yq '...' | XaShu sintaksis YAML uchun |
5 ta asosiy g'oya
jqhar JSON ishida —grep/awkbilan JSON parse qilmang.-rhar shell o'zgaruvchisi uchun — qo'shtirnoq olib tashlash uchun.nullehtiyot —?(optional) yoki// emptydefault ishlating.curl + jqpipeline — DevOps'ning eng ko'p ishlatadigan zanjiri.yq(Mike Farah) —jqsintaksisi YAML uchun. Kubernetes va Docker Compose'da kerak.
🎉 Endi sizda API integratsiya uchun barcha vositalar bor: curl + jq + yq. Keyingi bobda cron va systemd timer'lar — vazifalarni rejalashtirish.
Keyingi sahifa: 4. Cron va vazifalarni rejalashtirish →