Ich habe eine Json-Datei, die unter bestimmten Bedingungen aktualisiert werden muss.
Probe Json
{
"Actions" : [
{
"value" : "1",
"properties" : {
"name" : "abc",
"age" : "2",
"other ": "test1"
}
},
{
"value" : "2",
"properties" : {
"name" : "def",
"age" : "3",
"other" : "test2"
}
}
]
}
Ich schreibe ein Skript, das Jq verwendet, um einen Wert abzugleichen und zu aktualisieren, wie unten gezeigt
cat sample.json | jq '.Actions[] | select (.properties.age == "3") .properties.other = "no-test"'
Ausgabe (auf Terminal gedruckt)
{
"value": "1",
"properties": {
"name": "abc",
"age": "2",
"other ": "test1"
}
}
{
"value": "2",
"properties": {
"name": "def",
"age": "3",
"other": "no-test"
}
}
Während dieser Befehl die erforderliche Änderung vornimmt, gibt er den gesamten Json-Code auf dem Terminal aus und nimmt keine Änderungen an der Datei selbst vor.
Bitte geben Sie an, ob es eine Option gibt, mit der jq Änderungen direkt an der Datei vornehmen kann (ähnlich wie bei sed -i).
Dieser Beitrag befasst sich mit der Frage nach dem Fehlen des Äquivalents der Option "-i" von sed und insbesondere der beschriebenen Situation:
Ich habe eine Reihe von Dateien und es wäre nicht einfach, jede in eine separate Datei zu schreiben.
Es gibt mehrere Optionen, zumindest wenn Sie in einer Mac- oder Linux- oder ähnlichen Umgebung arbeiten. Ihre Vor- und Nachteile werden unter http://de.backup.org/2011/01/29/in-place-editing-of-files .__ diskutiert :
Eine ist einfach "&&" zu verwenden:
jq ... INPUT > INPUT.tmp && mv INPUT.tmp INPUT
Ein anderes ist die Verwendung des Dienstprogramms sponge
(Teil von GNU moreutils
):
jq ... INPUT | sponge INPUT
Die dritte Option kann nützlich sein, wenn es vorteilhaft ist, das Aktualisieren einer Datei zu vermeiden, wenn sie nicht geändert wird. Hier ist ein Skript, das eine solche Funktion veranschaulicht:
#!/bin/bash
function maybeupdate {
local f="$1"
cmp -s "$f" "$f.tmp"
if [ $? = 0 ] ; then
/bin/rm $f.tmp
else
/bin/mv "$f.tmp" "$f"
fi
}
for f
do
jq . "$f" > "$f.tmp"
maybeupdate "$f"
done
Sie möchten die Aktionsobjekte aktualisieren, ohne den Kontext zu ändern. Wenn Sie die Pipe dort haben, ändern Sie den Kontext für jede einzelne Aktion. Sie können das mit einigen Klammern kontrollieren.
$ jq --arg age "3" \
'(.Actions[] | select(.properties.age == $age).properties.other) = "no-test"' sample.json
Dies sollte ergeben:
{
"Actions": [
{
"value": "1",
"properties": {
"name": "abc",
"age": "2",
"other ": "test1"
}
},
{
"value": "2",
"properties": {
"name": "def",
"age": "3",
"other": "no-test"
}
}
]
}
Sie können die Ergebnisse in eine Datei umleiten, um die Eingabedatei zu ersetzen. Es werden keine direkten Updates für eine Datei vorgenommen, wie dies bei sed der Fall ist.
Meine Antwort auf eine doppelte Frage verwenden
Bei der Zuweisung wird das gesamte Objekt mit der ausgeführten Zuweisung gedruckt, sodass Sie
.Actions
des geänderten Actions-Arrays einen neuen Wert zuweisen können.Actions=([.Actions[] | if .properties.age == "3" then .properties.other = "no-test" else . end])
Ich habe eine if-Anweisung verwendet, aber wir können Ihren Code verwenden, um dasselbe zu tun
.Actions=[.Actions[] | select (.properties.age == "3").properties.other = "no-test"]
Das obige wird den gesamten Json mit .Actions
bearbeitet. Ausgeben Jq hat keine sed -i
-artige Funktionalität, aber alles, was Sie tun müssen, ist, es in einen sponge zurück in die Datei mit | sponge
zu leiten.
jq '.Actions=([.Actions[] | if .properties.age == "3" then .properties.other = "no-test" else . end])' sample.json | sponge sample.json