2017-10-08 3 views
0

Ich habe zwei .json Dateien, die erste enthält die Daten:jq - Karte Objektwerte mit starts()

data.json

[ 
{"ID_EXT_LARGE":"aaa_1234411","xy":"xyz"}, 
{"ID_EXT_LARGE":"bbb_1474411","xy":"cfg"}, 
{"ID_EXT_LARGE":"ccc_8944411","xy":"drt"}, 
{"ID_EXT_LARGE":"aaa_1234411","xy":"kai"} 
] 

Der andere die IDs enthält :

id_array.json

[ 
{"ID_EXT":"aaa","ID_WEB":30,"ID_ACC":"one"}, 
{"ID_EXT":"bbb","ID_WEB":40,"ID_ACC":"two"}, 
{"ID_EXT":"ccc","ID_WEB":50,"ID_ACC":"three"} 
] 

Jetzt versuche ich, die Eigenschaften "ID_WEB" und "ID_ACC" in die Objekte von data.json zu bekommen, mit dem Mapping von ID_EXT_LARGE und ID_EXT.

Das Problem ist, dass ID_EXT nur die ersten Zeichen von ID_EXT_LARGE enthält. Erwartetes Ergebnis - (sollte die erweiterte data.json-Datei):

data.json

[ 
{"ID_EXT_LARGE":"aaa_1234411","ID_WEB":30,"ID_ACC":"one","xy":"xyz"}, 
{"ID_EXT_LARGE":"bbb_1474411","ID_WEB":40,"ID_ACC":"two","xy":"cfg"}, 
{"ID_EXT_LARGE":"ccc_8944411","ID_WEB":50,"ID_ACC":"three","xy":"drt"}, 
{"ID_EXT_LARGE":"aaa_1234411","ID_WEB":30,"ID_ACC":"one","xy":"kai"} 
] 

Ich habe versucht, es für ID_WEB und wurde von so etwas wie dieses Denken, (die for-Schleife nur eine Idee war):

script.jq

def getIDWEB(id_array); 
     for i .... 
      if ."ID_EXT_LARGE"|startswith(id_array[i].ID_EXT) then id_array[i].ID_WEB end 
     end 
    ; 

    def setIDWEB(id_array): 
    .ID_WEB = getIDWEB(id_array) 
    ; 

    ($id_array) as $id_array 
    | map(setIDWEB($id_array)) 

Wahrscheinlich denke ich zu kompliziert und das ist eigentlich ein One-Liner?

Antwort

1

Hier ist ein Ansatz, der ein "Tabelle" -Objekt aus id_array.json erstellt. Diese Funktion erstellt die Tabelle:

def maketable: 
    reduce $id_array[] as $i (
    {} 
    ; .[$i.ID_EXT] = ($i | {ID_WEB,ID_ACC}) 
) 
; 

Mit der Probe id_array.json in $id_array dies gibt ein Objekt wie

{ 
    "aaa": { 
    "ID_WEB": 30, 
    "ID_ACC": "one" 
    }, 
    "bbb": { 
    "ID_WEB": 40, 
    "ID_ACC": "two" 
    }, 
    "ccc": { 
    "ID_WEB": 50, 
    "ID_ACC": "three" 
    } 
} 

Diese Funktion ein Objekt aus data.json nimmt und gibt die entsprechenden Suchschlüssel für die Tabelle:

def getkey: .ID_EXT_LARGE | split("_")[0] ; 

z

gegeben
{"ID_EXT_LARGE":"aaa_1234411","xy":"xyz"} 

es gibt

"aaa" 

Mit diesen beiden Funktionen kann das Ergebnis Ausgang mit generiert werden:

maketable as $idtable 
| map(. + $idtable[ getkey ]) 

Hier ist ein Skript, das alles zusammen bringt und verwendet spongedata.json zu aktualisieren :

#!/bin/bash 
jq -M --argfile id_array id_array.json ' 

    def maketable: 
     reduce $id_array[] as $i (
     {} 
     ; .[$i.ID_EXT] = ($i | {ID_WEB,ID_ACC}) 
    ) 
    ; 
    def getkey: .ID_EXT_LARGE | split("_")[0] ; 

     maketable as $idtable 
    | map(. + $idtable[ getkey ]) 

' data.json | sponge data.json 
Hier

ist data.json nach einem Probelauf:

[ 
    { 
    "ID_EXT_LARGE": "aaa_1234411", 
    "xy": "xyz", 
    "ID_WEB": 30, 
    "ID_ACC": "one" 
    }, 
    { 
    "ID_EXT_LARGE": "bbb_1474411", 
    "xy": "cfg", 
    "ID_WEB": 40, 
    "ID_ACC": "two" 
    }, 
    { 
    "ID_EXT_LARGE": "ccc_8944411", 
    "xy": "drt", 
    "ID_WEB": 50, 
    "ID_ACC": "three" 
    }, 
    { 
    "ID_EXT_LARGE": "aaa_1234411", 
    "xy": "kai", 
    "ID_WEB": 30, 
    "ID_ACC": "one" 
    } 
] 

Beachten Sie, dass als peak Punkte aus maketable ersetzt werden könnte

def maketable: INDEX($id_array[]; .ID_EXT) | map_values(del(.ID_EXT)) ; 

wenn die allgemeinere INDEX builtin (Definition unten) verfügbar.

+0

Wenn Ihr jq 'INDEX/1 'hat, können Sie Folgendes schreiben, anstatt' maketable' zu ​​verwenden: INDEX (.ID_EXT) | Kartenwerte (del (.ID_EXT)) – peak