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-rfür reine String-Ausgabe in Skripten hinzu select()filtert Arrays nach Bedingung — unterstützt String-Übereinstimmung, numerische Vergleiche und Regex mittest()- Erstellen Sie neue JSON-Strukturen mit Objektkonstruktion
{key: .field}undmap()für Array-Transformationen - Kombinieren Sie mit
curl,kubectl,terraformunddockerfür Automatisierung in der Praxis sort_by(),group_by(),length,addhandhaben 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