jq ist der JSON-Prozessor für die Kommandozeile, den jeder Linux-Administrator und DevOps-Engineer in seinem Werkzeugkasten haben sollte. Wenn Sie mit REST-APIs arbeiten, Kubernetes-Ausgaben parsen, Terraform-State verarbeiten oder Daten aus Logdateien extrahieren, ermöglicht Ihnen jq das Schneiden, Filtern und Transformieren von JSON direkt vom Terminal aus — ohne Python-Skript.

Dieser Leitfaden deckt alles von der einfachen Feldextraktion bis zu fortgeschrittenen Transformationen ab, mit praxisnahen Beispielen, die Sie täglich verwenden werden.

Voraussetzungen

  • Ein Linux-System (beliebige Distribution)
  • Grundlegende Vertrautheit mit Shell-Pipes und Kommandozeilen-Tools
  • JSON-Daten zum Arbeiten (wir verwenden durchgehend Beispiele)

jq installieren

Unter Debian/Ubuntu:

sudo apt update && sudo apt install -y jq

Unter RHEL/Fedora/AlmaLinux:

sudo dnf install -y jq

Unter Alpine:

sudo apk add jq

Unter macOS:

brew install jq

Überprüfen:

jq --version

jq vs. andere JSON-Verarbeitungs-Tools

ToolAm besten fürNachteile
jqSchnelle CLI-Transformationen, Shell-PipesKomplexe Logik wird umständlich
Python jsonMehrstufige Verarbeitung, komplexe LogikBenötigt Python-Runtime, mehr Code
yqYAML-Verarbeitung (jq-ähnliche Syntax)Separate Installation, YAML-spezifisch
fxInteraktive JSON-ExplorationNicht skriptfähig
gronJSON greppbar machenUnidirektional (nur Flatten)

jq gewinnt, wenn Sie schnelle, skriptfähige Transformationen in einer Pipeline mit null Abhängigkeiten über die Binärdatei hinaus benötigen.

Grundlagen von jq: Daten extrahieren

Der Identity-Filter

Die einfachste jq-Operation formatiert JSON schön:

echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.'
{
  "name": "nginx",
  "version": "1.25.3",
  "status": "running"
}

Felder extrahieren

Verwenden Sie Punkt-Notation, um bestimmte Werte zu extrahieren:

echo '{"name":"nginx","version":"1.25.3","status":"running"}' | jq '.name'
"nginx"

Um den reinen String ohne Anführungszeichen zu erhalten, fügen Sie -r hinzu:

echo '{"name":"nginx","version":"1.25.3"}' | jq -r '.name'
nginx

Das -r-Flag ist essentiell für Skripte. Ohne es gibt jq JSON-kodierte Strings (mit Anführungszeichen) aus, was Variablenzuweisungen und Vergleiche in bash kaputt macht.

Verschachtelte Objekte

echo '{"server":{"host":"10.0.0.1","port":8080}}' | jq '.server.port'
8080

Array-Zugriff

echo '["nginx","apache","caddy"]' | jq '.[0]'
"nginx"

Alle Elemente abrufen:

echo '["nginx","apache","caddy"]' | jq '.[]'
"nginx"
"apache"
"caddy"

Mit echten API-Antworten arbeiten

Hier ist ein realistisches Szenario: Eine REST-API abfragen und das Benötigte extrahieren.

# GitHub-Benutzerinfo abrufen
curl -s https://api.github.com/users/torvalds | jq '{login, name, public_repos, followers}'
{
  "login": "torvalds",
  "name": "Linus Torvalds",
  "public_repos": 7,
  "followers": 223000
}

Aus Arrays von Objekten extrahieren

Die meisten APIs geben Arrays zurück. So arbeiten Sie damit:

# API-Antwort simulieren
cat << 'EOF' | jq '.servers[] | {name, status}'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "web-02", "status": "stopped", "cpu": 0},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "name": "web-01",
  "status": "running"
}
{
  "name": "web-02",
  "status": "stopped"
}
{
  "name": "db-01",
  "status": "running"
}

JSON-Daten mit jq filtern

Die select()-Funktion

Arrays auf passende Elemente filtern:

cat << 'EOF' | jq '.servers[] | select(.status == "running")'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "web-02", "status": "stopped", "cpu": 0},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "name": "web-01",
  "status": "running",
  "cpu": 45
}
{
  "name": "db-01",
  "status": "running",
  "cpu": 78
}

Numerische Vergleiche

# Server mit CPU-Auslastung über 50%
cat servers.json | jq '.servers[] | select(.cpu > 50) | .name'

Bedingungen kombinieren

# Laufende Server mit hoher CPU-Auslastung
cat servers.json | jq '.servers[] | select(.status == "running" and .cpu > 50)'

String-Übereinstimmung

# Server, deren Name "web" enthält
cat servers.json | jq '.servers[] | select(.name | contains("web"))'

Für Regex-Übereinstimmung:

# Namen, die einem Muster entsprechen
cat servers.json | jq '.servers[] | select(.name | test("web-[0-9]+"))'

JSON mit jq transformieren

Neue Objekte erstellen

Neue JSON-Strukturen aus vorhandenen Daten konstruieren:

cat << 'EOF' | jq '.servers[] | {hostname: .name, healthy: (.status == "running"), load: (.cpu / 100)}'
{
  "servers": [
    {"name": "web-01", "status": "running", "cpu": 45},
    {"name": "db-01", "status": "running", "cpu": 78}
  ]
}
EOF
{
  "hostname": "web-01",
  "healthy": true,
  "load": 0.45
}
{
  "hostname": "db-01",
  "healthy": true,
  "load": 0.78
}

map() für Array-Transformationen

Jedes Element in einem Array transformieren:

echo '[1,2,3,4,5]' | jq 'map(. * 2)'
[2, 4, 6, 8, 10]

Praktisches Beispiel — nur Namen in ein Array extrahieren:

cat servers.json | jq '[.servers[].name]'
["web-01", "web-02", "db-01"]

Sortieren und Gruppieren

# Nach CPU absteigend sortieren
cat servers.json | jq '.servers | sort_by(.cpu) | reverse'

# Nach Status gruppieren
cat servers.json | jq '.servers | group_by(.status)'

Aggregationen

# Server zählen
cat servers.json | jq '.servers | length'

# Durchschnittliche CPU
cat servers.json | jq '.servers | map(.cpu) | add / length'

# Maximale CPU
cat servers.json | jq '.servers | max_by(.cpu) | .name'

jq in Shell-Skripten

Ergebnisse in Variablen speichern

#!/bin/bash
response=$(curl -s https://api.github.com/users/torvalds)

name=$(echo "$response" | jq -r '.name')
repos=$(echo "$response" | jq -r '.public_repos')

echo "User: $name has $repos public repos"

Achtung: Setzen Sie die Variable in echo "$response" immer in Anführungszeichen. Variablen ohne Anführungszeichen verlieren Leerzeichen und brechen das JSON-Parsing.

Über JSON-Arrays iterieren

#!/bin/bash
# Jeden Server von der API verarbeiten
curl -s https://api.example.com/servers | jq -r '.[] | .name' | while read -r server; do
    echo "Checking $server..."
    ping -c 1 -W 2 "$server" > /dev/null 2>&1 && echo "  UP" || echo "  DOWN"
done

Konfigurationsdateien aus JSON generieren

# JSON-Inventar in /etc/hosts-Einträge konvertieren
cat inventory.json | jq -r '.hosts[] | "\(.ip)\t\(.hostname)"' >> /etc/hosts

Bedingte Verarbeitung

#!/bin/bash
status=$(curl -s https://api.example.com/health | jq -r '.status')

if [ "$status" != "healthy" ]; then
    echo "ALERT: Service is $status" | mail -s "Health Check Failed" admin@example.com
fi

JSON mit jq modifizieren

Werte aktualisieren

echo '{"version": "1.0", "debug": false}' | jq '.version = "2.0" | .debug = true'
{
  "version": "2.0",
  "debug": true
}

Felder hinzufügen

echo '{"name": "app"}' | jq '. + {"env": "production", "replicas": 3}'

Felder löschen

echo '{"name":"app","secret":"abc123","version":"1.0"}' | jq 'del(.secret)'

Verschachtelte Werte aktualisieren

echo '{"database":{"host":"old-host","port":5432}}' | jq '.database.host = "new-host"'

jq-Rezepte aus der Praxis

Kubernetes Pod-Status parsen

kubectl get pods -o json | jq -r '.items[] | select(.status.phase != "Running") | "\(.metadata.name)\t\(.status.phase)"'

Terraform-Ausgabewerte extrahieren

terraform output -json | jq -r 'to_entries[] | "\(.key) = \(.value.value)"'

Docker-Container-Statistiken parsen

docker inspect $(docker ps -q) | jq '.[] | {name: .Name, ip: .NetworkSettings.IPAddress, status: .State.Status}'

CloudWatch-Log-Einträge verarbeiten

aws logs get-log-events --log-group-name /app/prod --log-stream-name main \
  | jq -r '.events[] | "\(.timestamp | . / 1000 | strftime("%Y-%m-%d %H:%M:%S")) \(.message)"'

CSV-Ausgabe aus JSON

cat servers.json | jq -r '.servers[] | [.name, .status, (.cpu | tostring)] | @csv'
"web-01","running","45"
"web-02","stopped","0"
"db-01","running","78"

Fehlerbehebung

“parse error: Invalid numeric literal”: Ihre Eingabe ist kein gültiges JSON. Validieren Sie es zuerst mit jq '.' file.json. Häufige Ursache: Die API hat HTML (Fehlerseite) statt JSON zurückgegeben.

“null”-Ausgabe, wenn Sie Daten erwarten: Der Feldname ist falsch oder existiert nicht an diesem Pfad. Verwenden Sie jq 'keys', um verfügbare Felder anzuzeigen, oder jq '.' | head -20, um die Struktur zu inspizieren.

Anführungszeichen in Variablenzuweisungen: Verwenden Sie immer jq -r (raw output) beim Zuweisen zu Shell-Variablen. Ohne es erhalten Sie "value" statt value, was String-Vergleiche kaputt macht.

“Cannot iterate over null”: Sie versuchen über ein Feld zu iterieren (.[]), das null oder fehlend ist. Fügen Sie den optionalen Operator hinzu: .field[]? oder prüfen Sie mit select(. != null).

Leerzeichen-Probleme in Pipes: Setzen Sie Ihre Variablen in Anführungszeichen. echo $json | jq '.' bricht bei Leerzeichen. Verwenden Sie stattdessen echo "$json" | jq '.'.

Zusammenfassung

  • jq ist das Standard-Tool für JSON-Verarbeitung auf der Kommandozeile — eine Binärdatei, keine Abhängigkeiten, funktioniert überall
  • Verwenden Sie .field, .[index] und .[] für grundlegende Extraktion; fügen Sie -r für reine String-Ausgabe in Skripten hinzu
  • select() filtert Arrays nach Bedingung — unterstützt String-Übereinstimmung, numerische Vergleiche und Regex mit test()
  • Erstellen Sie neue JSON-Strukturen mit Objektkonstruktion {key: .field} und map() für Array-Transformationen
  • Kombinieren Sie mit curl, kubectl, terraform und docker für Automatisierung in der Praxis
  • sort_by(), group_by(), length, add handhaben Sortierung und Aggregation
  • Modifizieren Sie JSON mit Zuweisung (.key = value), Addition (. + {}) und Löschung (del(.key))
  • Verwenden Sie immer das -r-Flag und setzen Sie Variablen in Anführungszeichen, wenn Sie jq in bash-Skripte integrieren

Bash Scripting for Sysadmins: The Essential Guide | Install Security Updates from the Command Line in Ubuntu