jq - 使用存储在变量中的对象标识符索引列表进行过滤

时间:2018-04-23 01:45:37

标签: json jq

我正在编写一个可重复使用的Bash脚本,该脚本允许我查询API以获取有关议会成员的数据并以csv格式存储它。

API的json响应有很多键(名称,性别,生日,委员会成员,投票......),并且,根据我想做的事情,我并不总是希望捕获相同的键。所以我想抽象代码的这一部分,以便能够编写:

from PIL import Image
from numpy import array

def convert(arr, cont1, cont2, cont3, repet1, repet2, repet3):

    if(cont1 != repet1):
        if(cont2 != repet2):
            if(cont3 != repet3):
                test = arr[repet1][repet2][repet3]
                if(test == 255):
                    arr[repet1][repet2][repet3] = 1
                    return convert(arr, cont1, cont2, cont3, repet1, repet2, repet3 +1)
                else:
                    arr[repet1][repet2][repet3] = 0
                    return convert(arr, cont1, cont2, cont3, repet1, repet2, repet3 +1)
            else:
                return convert(arr, cont1, cont2, cont3, repet1, repet2 + 1, 0)    
        else:
            return convert(arr, cont1, cont2, cont3, repet1 + 1, 0, 0)
    else:
        return arr


def convertAgain(binary, cont4, cont5, cont6, repet4, repet5, repet6):

    if(cont4 != repet4):
        if(cont5 != repet5):
            if(cont6 != repet6):
                test = binary[repet4][repet5][repet6]
                if(test == 1):
                    binary[repet4][repet5][repet6] = 255
                    return convertAgain(binary, cont4, cont5, cont6, repet4, repet5, repet6 + 1)
                else:
                    binary[repet4][repet5][repet6] = 0
                    return convertAgain(binary, cont4, cont5, cont6, repet4, repet5, repet6 + 1)
            else:
                return convertAgain(binary, cont4, cont5, cont6, repet4, repet5 + 1, 0)    
        else:
            return convertAgain(binary, cont4, cont5, cont6, repet4 + 1, 0, 0)
    else:
        return binary

def main():

    img = Image.open("put an image to try it")
    arr = array(img)
    len1 = len(arr)
    len2 = len(arr[0])
    len3 = len(arr[0][0])
    binary = convert(arr, len1, len2, len3, 0, 0, 0)
    print(binary)
    new = convertAgain(binary, len1, len2, len3, 0, 0, 0)
    print(new)
main();

这样它被jq解释为

mp_keys= a,b,c,d

curl https://mp.com | jq '. | [$mp_keys] | @csv'

我没有变量格式的集合结构,因此可能是:

  • jq '. | [.a, .b, .c, .d] | @ csv'
  • mp_keys="a,b,c,d"
  • mp_keys=".a, .b, .c, .d"

我知道在jq中我可以使用以下结构:

mp_key1=a, mp_key2=b, mp_key3=c, mp_key4=d

但很明显很快就会变得单调乏味。

最后我还可以将jq命令构建为字符串,然后将jq --arg mp_key1 "${mp_key1}" --arg mp_key2 "${mp_key2}" --arg mp_key3 "${mp_key3}" --arg mp_key4 "${mp_key4}" '. | [.[$mp_key1], .[$mp_key2], .[$mp_key3], .[$mp_key4]] | @csv' 应用于它,但我更喜欢使用正确的jq解决方案。

修改

我将打破@ peak的回答以供将来参考,因为它对于了解发生了什么非常有用。他的回答转载如下:

eval

首先,了解jq会:

非常重要
  1. 首先评估mp_keys="a,b,c,d" echo '{"a":1, "b":2, "c":3, "d": 4}' | jq -r --arg mpk "$mp_keys" ' ($mpk|split(",")) as $mpkeys | [ .[ $mpkeys[] ] ] | @csv ' 的值,这意味着在$mpkeys上执行split(",")
  2. 然后传递通过$mpk发送的json。
  3. 所以我们也可以这样做,以了解发生了什么。 echo告诉jq优先处理这个部分,所以我们可以先用括号替换它的结果。

    1. 存储在( )中的字符串"a,b,c,d"将被拆分并存储到数组$mpk中,如section on split(str)of jq's manual中所述。
    2. 数组随后会存储到["a","b","c","d"]$mpkeys
    3. 这意味着初始代码的等价物可以写成:

      as

      当然现在--arg是无用的,因为echo '{"a":1, "b":2, "c":3, "d": 4}' | jq -r --arg mpk "$mp_keys" ' ["a","b","c","d] as $mpkeys | [ .[ $mpkeys[] ] ] | @csv ' 可以保存我们的初始字符串。所以我们可以进一步简化:

      $mpk

      现在让我们分解echo '{"a":1, "b":2, "c":3, "d": 4}' | jq -r '["a","b","c","d] as $mpkeys | [ .[ $mpkeys[] ] ] | @csv '

      • 因为[ .[ $mpkeys[] ] ]是一个数组,$mpkeys代表数组的各个元素,相当于$mpkeys[]。我们现在有4个元素(字符串),而不是单个元素(数组),它们将被它们周围的过滤器(括号)单独转换。
      • 然后将
      • "a","b","c","d"包装到$mpkeys[]中,该.[]适用于4个元素中的每一个,因此相当于.["a"].["b"].["c"],{ {1}}。这些元素中的每一个都是通用对象索引,它等同于对象标识符索引形式(.["d"])为described in jq's manual
      • 最后的外部.a, .b, .c, .d只是将数据包装在数组中,这是将结果传递给[ ]所必需的。

      所以相当于上面的代码是:

      @csv

      这里echo '{"a":1, "b":2, "c":3, "d": 4}' | jq -r '["a","b","c","d] as $mpkeys | [ .["a"], .["b"], .["c"], .["d"] ] | @csv ' 没有任何意义,所以我们实际上有:

      $mpkeys

      我们有。

1 个答案:

答案 0 :(得分:1)

使用您的方法:

mp_keys="a,b,c,d"

echo '{"a":1, "b":2, "c":3, "d": 4}' |
  jq -r --arg mpk "$mp_keys" '
    ($mpk|split(",")) as $mpkeys
    | [ .[ $mpkeys[] ] ]
    | @csv '

会产生:

1,2,3,4