TL;DR — Kurzzusammenfassung

jq JSON-Verarbeitung auf der Kommandozeile unter Linux. JSON-Daten aus APIs und Konfigurationsdateien in bash-Skripten parsen, filtern, transformieren und automatisieren.

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

Tool Am besten für Nachteile
jq Schnelle CLI-Transformationen, Shell-Pipes Komplexe Logik wird umständlich
Python json Mehrstufige Verarbeitung, komplexe Logik Benötigt Python-Runtime, mehr Code
yq YAML-Verarbeitung (jq-ähnliche Syntax) Separate Installation, YAML-spezifisch
fx Interaktive JSON-Exploration Nicht skriptfähig
gron JSON greppbar machen Unidirektional (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

Verwandte Artikel