jq - 使用startswith()映射对象值

时间:2017-10-08 18:10:50

标签: json jq

我有两个.json文件,第一个包含数据:

  

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 个答案:

答案 0 :(得分: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] ;

e.g。给出

{"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
  )
;