Bemästra Linux-kommandoraden och Bash-skriptning · Lektion

Filtrera och välja JSON med jq-pipelines

Navigera i kapslade objekt och arrayer med jq-väljare, pipes och filtret select.

Lektion 1 av 413 steg

Filtrera och välja JSON med jq-pipelines är en gratis lektion i Bemästra Linux-kommandoraden och Bash-skriptning på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Bemästra Linux-kommandoraden och Bash-skriptning, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Bemästra Linux-kommandoraden och Bash-skriptning innehåller totalt 4 lektioner.

Vad är jq och varför ska det användas?

jq är ett lättviktigt och kraftfullt kommandoradsverktyg för att tolka, filtrera och omvandla JSON-data. Det är JSON-världens sed – Ni skickar JSON till verktyget via en pipe och får strukturerad utdata tillbaka.

  • Är förinstallerat i de flesta Linux-distributioner eller kan installeras med apt install jq / brew install jq
  • Fungerar sömlöst i skalets pipelines tillsammans med curl, cat och andra verktyg
  • Stöder filtrering, mappning, reduktion och formatkonvertering

Det grundläggande anropet är: jq '<filter>' file.json eller via en pipe som cat file.json | jq '<filter>'. Filtret . (punkt) är identitetsfiltret – det skriver ut hela dokumentet i läsbart format.

# Pretty-print a JSON file
jq '.' data.json

# Or pipe from curl
curl -s https://api.github.com/users/torvalds | jq '.'

Välj objektfält med punktnotation

För att komma åt ett fält i ett JSON-objekt använder Ni punktnotation: .fieldName. Ni kan kedja väljare för att navigera i nästlade objekt.

  • .name – fält på toppnivå
  • .address.city – nästlat fält
  • ."field-with-dash" – fält med specialtecken måste omges av citattecken

Om fältet inte finns returnerar jq null i stället för att generera ett fel. Därför är det säkert att använda i skript utan extra null-kontroller för valfria fält.

# Given: {"name":"Alice","address":{"city":"Berlin","zip":"10115"}}
echo '{"name":"Alice","address":{"city":"Berlin","zip":"10115"}}' | jq '.name'
# Output: "Alice"

echo '{"name":"Alice","address":{"city":"Berlin","zip":"10115"}}' | jq '.address.city'
# Output: "Berlin"

Åtkomst till matriselement och iterering

JSON-arrayer nås med hakparentesnotation. jq använder nollbaserad indexering.

  • .items[0] – första elementet
  • .items[-1] – sista elementet
  • .items[1:3] – utsnitt (från index 1 till, men inte inklusive, 3)
  • .items[] – packa upp arrayen: skriver ut varje element som ett separat värde (detta är iteratorn)

Iteratorn [] är grundläggande i jq-pipelines – den låter Er tillämpa efterföljande filter på varje element oberoende av de andra.

# Given an array of users
echo '[{"name":"Alice"},{"name":"Bob"},{"name":"Carol"}]' | jq '.[0]'
# Output: {"name":"Alice"}

# Iterate all elements and extract .name from each
echo '[{"name":"Alice"},{"name":"Bob"},{"name":"Carol"}]' | jq '.[].name'
# Output:
# "Alice"
# "Bob"
# "Carol"

Bygg jq-pipelines med pipe-operatorn

Precis som skalets pipe | har jq en egen intern pipe-operator. Den skickar utdata från ett filter som indata till nästa.

  • jq '.users[] | .name' – iterera över användare och hämta sedan namnet från var och en
  • jq '.data | .items[] | .id' – navigera till data, packa upp items och hämta id

Pipes i ett jq-uttryck gör det möjligt att bygga komplexa omvandlingar steg för steg. Varje steg tar emot det föregående stegets resultat – inklusive flera värden från en iterator.

Viktig insikt: när en iterator producerar N värden körs varje efterföljande filter N gånger, en gång per värde.

# Nested pipeline: navigate -> iterate -> extract
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' \
  | jq '.users[] | .name'
# Output:
# "Alice"
# "Bob"

# Chain more stages
echo '{"users":[{"name":"Alice","age":30},{"name":"Bob","age":25}]}' \
  | jq '.users[] | .age'
# Output:
# 30
# 25

Filtrera med select()

Filtret select(condition) släpper endast igenom ett värde om villkoret är sant; annars producerar det ingen utdata. Det motsvarar grep eller WHERE i SQL i jq.

  • select(.age > 18) – behåll objekt där åldern är större än 18
  • select(.status == "active") – jämförelse av likhet
  • select(.name | startswith("A")) – nästlat test av en sträng

Kombinera select med iteratorn för att filtrera arrayer: .items[] | select(.active) skriver endast ut element där .active är sanningsenligt.

# Filter array elements by a condition
echo '[{"name":"Alice","age":30},{"name":"Bob","age":17},{"name":"Carol","age":25}]' \
  | jq '.[] | select(.age >= 18) | .name'
# Output:
# "Alice"
# "Carol"

# Filter by string equality
echo '[{"name":"Alice","role":"admin"},{"name":"Bob","role":"user"}]' \
  | jq '.[] | select(.role == "admin") | .name'
# Output: "Alice"

Återskapa objekt och arrayer med {} och []

Med jq kan Ni omforma data genom att konstruera nya objekt med {} och nya arrayer med [].

  • {name: .name, city: .address.city} – välj och byt namn på fält i ett nytt objekt
  • [.items[] | .id] – samla itererade värden i en ny array
  • Kortform: {name, age} motsvarar {name: .name, age: .age}

Att omsluta en pipeline med [...] kallas arraykonstruktion och är nödvändigt när Ni vill ha en JSON-array som utdata i stället för en ström av värden.

# Reshape: keep only selected fields
echo '[{"id":1,"name":"Alice","password":"secret"},{"id":2,"name":"Bob","password":"secret"}]' \
  | jq '[.[] | {id, name}]'
# Output:
# [
#   {"id": 1, "name": "Alice"},
#   {"id": 2, "name": "Bob"}
# ]

# Collect filtered names into an array
echo '[{"name":"Alice","active":true},{"name":"Bob","active":false}]' \
  | jq '[.[] | select(.active) | .name]'
# Output: ["Alice"]

Arbeta med nästlade arrayer och rekursiv genomgång

JSON från verkliga system är ofta djupt nästlad. jq tillhandahåller två verktyg för djup navigering:

  • .a.b.c – explicit sökväg när strukturen är känd
  • .. | .fieldName? – rekursiv genomgång: går igenom varje nod i trädet och skriver ut värden där nyckeln finns

Operatorn ? (try) undertrycker fel när ett fält inte finns vid en viss nod, vilket är avgörande när Ni använder rekursiv genomgång på heterogena träd.

Använd rekursiv genomgång sparsamt för stora dokument – varje nod besöks och det kan gå långsamt. Föredra explicita sökvägar när strukturen är förutsägbar.

# Explicit deep path
echo '{"a":{"b":{"c":42}}}' | jq '.a.b.c'
# Output: 42

# Recursive descent: find all "id" values anywhere in the tree
echo '{"users":[{"id":1,"profile":{"id":99}},{"id":2}]}' \
  | jq '.. | .id?'
# Output:
# 1
# 99
# 2

Praktiskt exempel: tolka API-svar från curl

Ett av de vanligaste användningsområdena för jq är att tolka svar från REST-API:er som hämtats med curl. Genom att kombinera curl -s (tyst läge) med en jq-pipeline får Ni ren dataextrahering som lämpar sig för skript.

  • Extrahera ett enskilt värde: curl -s URL | jq '.field'
  • Bygg en sammanfattningstabell: iterera över en array och återskapa objekt med endast de fält Ni behöver
  • Använd -r (rå utdata) för att ta bort de omgivande citattecknen från strängvärden – nödvändigt när värden tilldelas skalvariabler

Tips: lägg alltid till -r när jq-utdata ska användas som en skalvariabel eller skickas vidare till ett annat kommando.

#!/usr/bin/env bash
# Fetch GitHub repo info and extract specific fields
REPO="torvalds/linux"
RESPONSE=$(curl -s "https://api.github.com/repos/${REPO}")

# Extract fields
STARS=$(echo "$RESPONSE" | jq -r '.stargazers_count')
LANG=$(echo  "$RESPONSE" | jq -r '.language')
DESC=$(echo  "$RESPONSE" | jq -r '.description')

echo "Stars : $STARS"
echo "Lang  : $LANG"
echo "Desc  : $DESC"

Använda map() och map_values()

jq tillhandahåller två praktiska högre ordningens funktioner för att omvandla samlingar:

  • map(f) – tillämpar filtret f på varje element i en array och returnerar en ny array. Motsvarar [.[] | f].
  • map_values(f) – tillämpar f på varje värde i ett objekt eller en array och bevarar nycklarna/indexen.

Dessa funktioner är mer lättlästa än att manuellt omsluta pipelines med [] och följer idiomatisk jq-stil för omvandlingar som ska förbli arrayer.

# map: extract a field from each element
echo '[{"name":"Alice","score":95},{"name":"Bob","score":80}]' \
  | jq 'map(.name)'
# Output: ["Alice", "Bob"]

# map with select: filter + transform in one step
echo '[{"name":"Alice","score":95},{"name":"Bob","score":60}]' \
  | jq 'map(select(.score >= 70) | .name)'
# Output: ["Alice"]

# map_values: multiply every value in an object by 2
echo '{"a":1,"b":2,"c":3}' | jq 'map_values(. * 2)'
# Output: {"a":2,"b":4,"c":6}

Hantera valfria fält och standardvärden med //

JSON-data från externa källor är ofta inkonsekvent – fält kan saknas eller vara null. jq tillhandahåller alternativoperatorn // (dubbelt snedstreck) för att ange ett standardvärde.

  • .nickname // "anonymous" – använd .nickname om det inte är null/false, annars "anonymous"
  • .count // 0 – numeriskt standardvärde
  • Kombinera med select: select((.status // "inactive") == "active")

Detta är mycket mer koncist än motsvarigheten i skalet, ${VAR:-default}, och kan enkelt kombineras i längre pipelines.

# Provide defaults for missing/null fields
echo '[{"name":"Alice","role":"admin"},{"name":"Bob"}]' \
  | jq '[.[] | {name, role: (.role // "user")}]'
# Output:
# [
#   {"name": "Alice", "role": "admin"},
#   {"name": "Bob",   "role": "user"}
# ]

# Numeric default
echo '{"items":[1,2,3]}' | jq '.total // 0'
# Output: 0

Praktiskt skript: JSON-loggtolk

Strukturerad JSON-loggning är standard i moderna system. Här är ett realistiskt skript som läser en loggfil med JSON-objekt avgränsade med radbrytningar, filtrerar fram felposter och formaterar en lättläst sammanfattning.

Viktiga mönster:

  • -c (kompakt utdata) – ett JSON-objekt per rad, användbart när utdata skickas till skal-loopar
  • --arg name value – injicera en skalvariabel som ett jq-strängargument
  • select för filtrering efter loggnivå
  • -r för rå strängutdata som passar för echo
#!/usr/bin/env bash
# Parse newline-delimited JSON logs and report ERRORs
# Each log line: {"level":"ERROR","msg":"...","ts":"2024-01-15T10:23:00Z","svc":"auth"}

LOG_FILE="/var/log/app/app.log"
LEVEL="ERROR"

echo "=== $LEVEL entries in $LOG_FILE ==="

jq -r --arg lvl "$LEVEL" \
  'select(.level == $lvl) | "[\(.ts)] [\(.svc)] \(.msg)"' \
  "$LOG_FILE"

# Count errors per service
echo ""
echo "=== Error count by service ==="
jq -r --arg lvl "$LEVEL" \
  'select(.level == $lvl) | .svc' "$LOG_FILE" \
  | sort | uniq -c | sort -rn

Kunskapskontroll: beteendet hos jq select()

Testa din förståelse av hur select() fungerar i en jq-pipeline.

Följande kommando används:

echo '[{"name":"Alice","age":30},{"name":"Bob","age":17},{"name":"Carol","age":22}]' | jq '[.[] | select(.age >= 18) | .name]'

Vad blir resultatet?

Lektionssammanfattning: jq-pipelines för JSON-filtrering

Du har gått igenom de viktigaste jq-verktygen för att navigera i och filtrera JSON från kommandoraden:

  • Punktnotation (.field, .a.b.c) väljer fält från objekt
  • Åtkomst till arrayer (.[0], .[]) indexerar och itererar över arrayer
  • Pipe-operatorn (|) kopplar samman filter; varje steg bearbetar alla värden från föregående steg
  • select(cond) filtrerar värden och släpper endast igenom dem där villkoret är sant
  • Konstruktion av objekt och arrayer ({}, [], map()) omformar data till nya strukturer
  • Alternativoperatorn (//) anger standardvärden för null eller saknade fält
  • Flaggan -r tar bort citattecken vid tilldelning till skalvariabler; --arg infogar skalvariabler på ett säkert sätt
  • Rekursiv sökning (.. | .field?) söker i djupt nästlade träd när sökvägen är okänd

Med dessa byggstenar kan du omvandla alla JSON-svar från API:er, loggfiler eller konfigurationer till exakt den data dina skript behöver — utan att lämna terminalen.

Gratis att börja

Lär dig Bash med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
22
Lektioner
88

Vanliga frågor

Är lektionen ”Filtrera och välja JSON med jq-pipelines” gratis?

Ja – hela texten till ”Filtrera och välja JSON med jq-pipelines” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Bemästra Linux-kommandoraden och Bash-skriptning, kan Ni uppgradera till CoddyKit PRO. Kursen i Bemästra Linux-kommandoraden och Bash-skriptning innehåller totalt 4 lektioner.

Vad lär jag mig i ”Filtrera och välja JSON med jq-pipelines”?

Navigera i kapslade objekt och arrayer med jq-väljare, pipes och filtret select. Ni övar på Bemästra Linux-kommandoraden och Bash-skriptning med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Bemästra Linux-kommandoraden och Bash-skriptning?

Du behöver inga förkunskaper. Utbildningen i Bemästra Linux-kommandoraden och Bash-skriptning på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Filtrera och välja JSON med jq-pipelines”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Bemästra Linux-kommandoraden och Bash-skriptning-lektionen?

Ja. Varje Bemästra Linux-kommandoraden och Bash-skriptning-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Filtrera och välja JSON med jq-pipelines
  2. Omforma och skapa JSON-objekt med jq
  3. Anropa REST-API:er med curl och jq tillsammans
  4. Redigera YAML-konfigurationsfiler med yq
← Tillbaka till Bemästra Linux-kommandoraden och Bash-skriptning