2017-10-08 126 views
0

我有两个以.json文件映射对象的值,第一个包含数据:JQ - 使用startswith()

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"} 
] 

另一种包含的ID :

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"} 
] 

现在我尝试使用ID_EXT_LARGE和ID_EXT的映射将“ID_WEB”和“ID_ACC”属性置入data.json的对象中。

问题是,ID_EXT只包含ID_EXT_LARGE的第一个字符。 预期结果 - (应该是扩展data.json文件):

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"} 
] 

我试了ID_WEB和正想着这样的事情,(for循环只是一个想法):

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)) 

大概我在想太复杂,这实际上是一个单线程?

回答

1

这是一个从id_array.json建立“表”对象的方法。这个函数创建该表:

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

随着样品id_array.json$id_array此返回类似

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

对象这个函数有一个对象从data.json和返回该表中的相应查找关键字:

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

eg鉴于

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

返回

"aaa" 

有了可以与产生的结果输出这两个功能:

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

下面是一个脚本,把一切融合在一起,并使用sponge更新data.json

#!/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 

这里是data.json一个样本运行后:

[ 
    { 
    "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" 
    } 
] 

注意,作为peak指出maketable可以用

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

取代,如果更一般的INDEX内置(下文定义)是可用。

def INDEX(stream; idx_expr): 
    reduce stream as $row (
    {} 
    ; .[$row|idx_expr| if type != "string" then tojson else . end] |= $row 
) 
; 
+0

如果你的jq有'INDEX/1',你可以使用'maketable'来编写以下代码:INDEX(.ID_EXT)| map_values(德尔(.ID_EXT)) – peak