In der folgenden JSON-Datei
{
"email": "xxx",
"pass": "yyy",
"contact": [
{
"id": 111,
"name": "AAA"
}
],
"lname": "YYY",
"name": "AAA",
"group": [
{
"name": "AAA",
"lname": "YYY",
}
],
Ich muss nach dem Schlüssel "Name" suchen und seinen Wert an allen Stellen durch "XXX" ersetzen. Welcher jq-Befehl macht das?
Die Zuweisungsoperationen von jq können eine Aktualisierung an so vielen Orten gleichzeitig durchführen, wie Sie benennen können, und sind für diese Art von Situation vorgesehen. Sie können verwenden
auf jedes Feld mit dem Namen „name“ überall und ersetzen Sie den Wert in jedem auf einmal finden mit „XXXX“ und gibt das resultierende Objekt zurück .
Dies ist nur das
..|.a?
Beispiel aus der Dokumentation zum rekursiven Abstieg in Kombination mit der Aktualisierungszuweisung .Es nutzt den rekursiven Abstieg Operator
..
jeden einzelnen Wert im Baum zu finden, zieht dann das Feld „Namen“ von jedem von ihnen mit.name
, unterdrückt Fehler von nicht passenden Werten mit?
und aktualisiert dann das Objekt in allen diesen Orten auf einmal mit "XXXX" unter Verwendung des Aktualisierungszuweisungsoperators|=
und gibt das neue Objekt aus.Dies funktioniert unabhängig von der Dateistruktur und aktualisiert jedes Namensfeld überall.
Wenn die Datei immer diese Struktur hat und es sich um die bestimmten "Namens" -Felder handelt, die Sie ändern möchten, und nicht nur um einen alten Namen, können Sie sie auch einfach auflisten und ihnen auch als Gruppe zuweisen:
Dies macht die gleiche Zuordnung zu
alles auf einmal. Dies ist besonders nützlich, wenn die Datei möglicherweise andere Namensfelder enthält, die nichts mit Ihnen zu tun haben und die Sie nicht ändern möchten. Es werden nur die drei dort genannten Standorte gefunden und alle gleichzeitig aktualisiert.
Wenn der Wert nur ein Literal ist, wie es hier ist, dann funktioniert auch die einfache Zuordnung mit
=
und speichert Ihnen ein Zeichen:(..|.name?)="XXXX"
- Sie möchten dies auch, wenn Ihr Wert basierend auf dem gesamten Objekt der obersten Ebene berechnet wird. Wenn stattdessen wollen Sie den neuen Namen auf der alten Basis zu berechnen, Sie müssen zu verwenden|=
. Wenn ich nicht sicher bin, was ich verwenden soll,|=
hat sich das Verhalten in den Eckfällen im Allgemeinen etwas besser.Wenn Sie mehrere Ersetzungen durchführen müssen , können Sie diese zusammen leiten:
aktualisiert überall die Felder "name" und "lname" und gibt das gesamte aktualisierte Objekt einmal aus.
Einige andere Ansätze, die funktionieren könnten:
Sie können auch sehr explizit angeben, mit was Sie auswählen
Das findet alles, dann nur die Objekte, dann nur die Objekte, die einen "Namen" haben, dann das Namensfeld für diese Objekte und führt die gleiche Aktualisierung wie zuvor durch.
walk
Funktion auch folgende Aufgaben ausführen :walk(.name?="XXXX")
. Alle anderen Versionen funktionieren mit der neuesten Version 1.5.Ein alternatives Multi-Update könnte sein
Das findet alles mit einem Namen und setzt dann sowohl "name" als auch "lname" für jedes Objekt unter Verwendung der arithmetischen Aktualisierungszuweisung
*=
und des Zusammenführungsverhaltens+
für Objekte .quelle
alternativ
jtc
basierte Lösung:quelle