【问题标题】:jq - parse structure and save values in bash variablejq - 解析结构并将值保存在 bash 变量中
【发布时间】:2020-05-07 12:25:12
【问题描述】:

我有一个json输入如下

{
  "unique": 1924,
  "coordinates": [
    {
      "time": "2015-01-25T00:00:01.683",
      "xyz": [
        {
          "z": 4,
          "y": 2,
          "x": 1,
          "id": 99,
          "inner_arr" : [
          {
              "a": 1,
              "b": 2
          },
          {
              "a": 3,
              "b": 4
          }
          ]
        },
        {
          "z": 9,
          "y": 9,
          "x": 8,
          "id": 100,
          "inner_arr" : [
          {
              "a": 1,
              "b": 2
          },
          {
              "a": 3,
              "b": 4
          }
          ]
        },
        {
          "z": 9,
          "y": 6,
          "x": 10,
          "id": 101,
          "inner_arr" : [
          {
              "a": 1,
              "b": 2
          },
          {
              "a": 3,
              "b": 4
          }
          ]
        }
      ]
    },
    {
      "time": "2015-01-25T00:00:02.790",
      "xyz": [
        {
          "z": 0,
          "y": 3,
          "x": 7,
          "id": 99,
         "inner_arr" : [
          {
              "a": 1,
              "b": 2
          },
          {
              "a": 3,
              "b": 4
          }
          ]
        },
        {
          "z": 4,
          "y": 6,
          "x": 2,
          "id": 100,
          "inner_arr" : [
          {
              "a": 1,
              "b": 2
          },
          {
              "a": 3,
              "b": 4
          }
          ]
        },
        {
          "z": 2,
          "y": 9,
          "x": 51,
          "id": 101,
          "inner_arr" : [
          {
              "a": 1,
              "b": 2
          },
          {
              "a": 3,
              "b": 4
          }
          ]
        }
      ]
    }
  ]
}

我想用 jq 解析这个输入并将值存储在 bash 数组中:

#!/bin/bash

z=()
x=()
y=()
id=()
a=()
b=()

jq --raw-output '.coordinates[] | .xyz[] | (.z) as $z, (.y) as $y,7 (.x) as $x, (.id) as $id, .inner_arr[].a $a, .inner_arr[].b as $b | $z, $y, $x, $id, $a, $b' <<< "$input"


echo -e "${z}"

上述回显命令的预期输出:

4
9
9
0
4
2

echo -e "${a}"

上述回显命令的预期输出:

1
3
1
3
1
3
1
3
1
3
1
3

我怎样才能用 jq 做到这一点,一个 jq 调用以级联方式循环遍历所有数组? 我想通过调用 jq 一次并提取所有单个或数组值来节省 CPU。

【问题讨论】:

    标签: json linux bash loops jq


    【解决方案1】:

    您不能直接从 jq 设置环境变量(参见manual)。您可以做的是为 declare 内置函数生成一系列 bash 声明。我建议将声明存储在由declare 直接处理的中间bash 数组(使用mapfile)中,这样您就可以远离eval 等危险命令。

    mapfile -t < <(
        jq --raw-output '
            def m(exp): first(.[0] | path(exp)[-1]) + "=(" + (map(exp) | @sh) + ")";
            [ .coordinates[].xyz[] ]
            | m(.x), m(.y), m(.z), m(.id), m(.inner_arr[].a), m(.inner_arr[].b)
        ' input
    )
    
    declare -a "${MAPFILE[@]}"
    

    jq 脚本将所有xyz 对象打包在一个数组中,并使用m 函数对表示为路径表达式的每个字段进行过滤。该函数返回格式为field=(val1 val2... valN) 的字符串,其中字段名称是路径表达式的最后一个组成部分,即x 表示.xa 表示.inner_arr[].a(在数组的第一项上提取) .

    然后您可以使用declare -p var${var[@]} 检查shell 变量。 ${var} 仅指第一个元素。

    declare -p MAPFILE
    declare -p z
    echo a: "${a[@]}" / size = ${#a[@]}
    

    declare -a MAPFILE=([0]="x=(1 8 10 7 2 51)" [1]="y=(2 9 6 3 6 9)" [2]="z=(4 9 9 0 4 2)" [3]="id=(99 100 101 99 100 101)" [4]="a=(1 3 1 3 1 3 1 3 1 3 1 3)" [5]="b=(2 4 2 4 2 4 2 4 2 4 2 4)")
    declare -a z=([0]="4" [1]="9" [2]="9" [3]="0" [4]="4" [5]="2")
    a: 1 3 1 3 1 3 1 3 1 3 1 3 / size = 12
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 2015-10-13
      • 1970-01-01
      • 2013-02-27
      相关资源
      最近更新 更多