2016-06-19 11 views
2

ich eine JSON-Datei enthält mehrere Profile haben:jq: Hinzufügen von verschachtelten Objekt zu einem JSON

{ 
    "profile1": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook1" 
    }, 
    "default": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook2" 
    } 
} 

Ich möchte jq verwenden ein anderes Profil einfügen, „test“, so dass das Endergebnis sein wird

{ 
    "profile1": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook1" 
    }, 
    "default": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook2" 
    }, 
    "test": { 
    "user": "user3", 
    "channel": "channel3", 
    "hook": "hook3" 
    } 
} 

direkt in der Kommandozeile kann ich es tun mit:

cat filename | 
    jq '.+ { "test": { "user": "u3", "channel" : "c3", "hook": "w3" } }' 

Aber wenn ich es in meinem bash-Skript versuchen:

cat "$CONF_FILE" | 
    jq --arg p "$PROFILE" --arg u "$U" --arg c "$C" --arg w "$WH" \ 
    '.+ { $p: { "user": $u, "channel": $c, "hook": $w } }' ` 

Ich erhalte die folgende Fehlermeldung:

jq: error: syntax error, unexpected ':', expecting '}' (Unix shell quoting issues?) at <top-level>, line 1: 
.+ { $p: { "user": $u, "channel": $c, "hook": $w } } 
jq: error: syntax error, unexpected '}', expecting $end (Unix shell quoting issues?) at <top-level>, line 1: 
.+ { $p: { "user": $u, "channel": $c, "hook": $w } } 
jq: 2 compile errors 

Ich habe versucht, die Variable mit Anführungszeichen umgeben, aber dann bekomme ich nur die Zeichenfolge $ p:

cat "$CONF_FILE" | 
    jq --arg p "$PROFILE" --arg u "$U" --arg c "$C" --arg w "$WH" \ 
    '.+ { "$p": { "user": $u, "channel": $c, "hook": $w } }' 

Ergebnis:

{ 
    "profile1": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook1" 
    }, 
    "default": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook2" 
    }, 
    "$p": { 
    "user": "user3", 
    "channel": "channel3", 
    "hook": "hook3" 
    } 
} 



EDIT: Ich habe gefunden, was eine vorübergehende Lösung scheint, das Objekt in ein Array umzuwandeln, um den Wert der Bearbeitung (jetzt der Profilname ein Wert ist und kein Schlüssel) und zum Umwandeln des Array zurück auf ein Objekt :

cat "$CONF_FILE" | 
    jq --arg p "$PROFILE" --arg u "$U" --arg c "$C" --arg w "$WH" \ 
    'to_entries | .+ [ { "key": $p, "value": { "user": $u, "channel": $c, "hook": $w } } ] | from_entries' 

Es scheint roh, aber es funktioniert. Ich bin immer noch die Hoffnung für eine bessere Lösung ...

+0

sieht aus wie eine der Shell-Variablen, die Sie interpolieren ist leer – hek2mgl

+0

können Sie erarbeiten? Wenn ich die gleichen Variablen wie Werte anstelle von Schlüsseln verwende, funktioniert es. – apines

+0

Ich meine diese Variablen: '--arg" $ PROFIL "--arg" $ U "--arg c" $ C "--arg w" $ WH "'. Sind Sie sicher, dass sie alle gesetzt und nicht leer sind? – hek2mgl

Antwort

3

Verwenden Klammer um dynamische Schlüssel:

jq --arg p "$PROFILE" --arg u "$U" --arg c "$C" --arg w "$WH" \ 
'. + {($p): {"user": $u, "channel": $c, "hook": $w}}' "$CONF_FILE" 
+0

Funktioniert wie ein Charme, danke! – apines

0

Hier ist ein Skript, das eine Lösung Variablen env zeigt über die Umwelt bestand zuzugreifen:

#!/bin/bash 

CONF_FILE=data.json 

export P=test 
export U=user3 
export C=channel3 
export W=hook3 

jq ' 
    .[env.P] = { 
     user: env.U, 
     channel: env.C, 
     hook: env.W 
    } 
' "$CONF_FILE" 

Wenn data.json die Beispieldaten enthält dieses Skript sollte die Ausgabe

{ 
    "profile1": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook1" 
    }, 
    "default": { 
    "user": "user1", 
    "channel": "channel1", 
    "hook": "hook2" 
    }, 
    "test": { 
    "user": "user3", 
    "channel": "channel3", 
    "hook": "hook3" 
    } 
} 
produzieren