【问题标题】:Accessing JQ Variables Using Arguments使用参数访问 JQ 变量
【发布时间】:2021-04-21 07:10:39
【问题描述】:

我正在尝试根据此 JSON 的键获取值:

{
  "streams": {
    "vs-first": {
      "version": "2.33.0",
      "branch": "ewewew",
      "hash": "ewewewewe",
      "widgets": []
    },
    "vs-second": {
      "version": "1.58.0",
      "branch": "ewewew",
      "hash": "ewewew",
      "widgets": []
    },
    "vs-third": {
      "version": "1.42.0",
      "branch": "ewewew",
      "hash": "ewewe",
      "widgets": []
    },
    "vs-fourth": {
      "version": "1.58.0",
      "branch": "eewfwfef",
      "hash": "vvfffsfsf",
      "widgets": []
    },
    "vs-fifth": {
      "version": "1.39.0",
      "branch": "fvrvvsdvds",
      "hash": "vvsvdsvds",
      "widgets": [
        "1",
        "2",
        "3",
        "4"
      ]
    }
  }
}

这是我的脚本实现:

jq -r '.streams|keys[]' $vsconfig | while read key ; do
    if [ $key == "[" ] || [ $key == "]" ]; then
      continue
    fi

    if [ $key == "vs-first" ]; then
      version=$(jq -r '.streams.vs-first.version' $vsconfig)
      branch=$(jq -r '.streams.vs-first.branch' $vsconfig)
      hash=$(jq -r '.streams.vs-first.hash' $vsconfig)

      filename="one_file-$version-$branch-$hash.zip"
      createdUrl="$someurl/$version/$filename"

      curl $createdUrl --output ./som/random/dir --create-dirs
      ...
    else
      version=$(jq -r --arg v keyvar $key 'streams.[$keyvar].branch' $vsconfig)
      branch=`jq --arg keyvar "streams.$key.branch" '$keyvar' $vsconfig`
      hash=`jq --arg keyvar "streams.$key.hash" '$keyvar' $vsconfig`

      filename = "$key-$version"
      if [ $branch == "some_branch" ]; then
        filename="one_file-$version-$branch-$hash.zip"
      else
        filename="$filename.zip"
      fi

      curl $createdUrl --output ./som/random/dir --create-dirs
    fi

    echo "Version: $version Branch: $branch Hash: $hash"
done

我尝试了多种格式,即:

version=$(jq -r --arg v keyvar $key 'streams.[$keyvar].branch' $vsconfig)

还有:

branch=`jq --arg keyvar "streams.$key.branch" '$keyvar' $vsconfig`

它给出了这个错误:

jq: error: support/0 is not defined at <top-level>, line 1:

【问题讨论】:

  • 我正在尝试遍历streams.&lt;name&gt;,获取版本、分支和哈希,并使用它来构建一个 url 来发出网络请求。我是jq 的新手,如果有办法在单个jq 调用中做到这一点,请帮忙。谢谢@JohnKugelman

标签: linux bash shell jq


【解决方案1】:

jq 相当复杂。最好的选择可能是在单个 jq 调用中完成所有这些操作,并且使用最少的或没有 bash 脚本。

仅值

首先,您可以通过将[] 应用于.streams 对象来获取每个版本/分支/哈希对象。在对象或键/值映射上使用 [] 会提取值并丢弃键。

$ jq -c '.streams[]' vs.json
{"version":"2.33.0","branch":"ewewew","hash":"ewewewewe","widgets":[]}
{"version":"1.58.0","branch":"ewewew","hash":"ewewew","widgets":[]}
{"version":"1.42.0","branch":"ewewew","hash":"ewewe","widgets":[]}
{"version":"1.58.0","branch":"eewfwfef","hash":"vvfffsfsf","widgets":[]}
{"version":"1.39.0","branch":"fvrvvsdvds","hash":"vvsvdsvds","widgets":[]}

然后,您可以通过将上述对象传递到一个过滤器来获取您感兴趣的各个字段,该过滤器抓取 .version.branch.hash 并将三个值放入一个数组中:

$ jq -c '.streams[] | [.version, .branch, .hash]' vs.json
["2.33.0","ewewew","ewewewewe"]
["1.58.0","ewewew","ewewew"]
["1.42.0","ewewew","ewewe"]
["1.58.0","eewfwfef","vvfffsfsf"]
["1.39.0","fvrvvsdvds","vvsvdsvds"]

要让它格式化结果,您可以生成字符串而不是列表,并使用\(...) 嵌入值。 -r 标志告诉它打印原始结果:换句话说,打印不带引号的字符串。

$ jq -r '.streams[] | "Version: \(.version) Branch: \(.branch) Hash: \(.hash)"' vs.json
Version: 2.33.0 Branch: ewewew Hash: ewewewewe
Version: 1.58.0 Branch: ewewew Hash: ewewew
Version: 1.42.0 Branch: ewewew Hash: ewewe
Version: 1.58.0 Branch: eewfwfef Hash: vvfffsfsf
Version: 1.39.0 Branch: fvrvvsdvds Hash: vvsvdsvds

键和值

要将键添加到组合中,您可以使用to_entries,它从对象中提取键/值对:

$ jq -c '.streams | to_entries[]' vs.json
{"key":"vs-first","value":{"version":"2.33.0","branch":"ewewew","hash":"ewewewewe","widgets":[]}}
{"key":"vs-second","value":{"version":"1.58.0","branch":"ewewew","hash":"ewewew","widgets":[]}}
{"key":"vs-third","value":{"version":"1.42.0","branch":"ewewew","hash":"ewewe","widgets":[]}}
{"key":"vs-fourth","value":{"version":"1.58.0","branch":"eewfwfef","hash":"vvfffsfsf","widgets":[]}}
{"key":"vs-fifth","value":{"version":"1.39.0","branch":"fvrvvsdvds","hash":"vvsvdsvds","widgets":[]}}

抽出不同的字段就变成了:

$ jq -c '.streams | to_entries[] | [.key, .value.version, .value.branch, .value.hash]' vs.json
["vs-first","2.33.0","ewewew","ewewewewe"]
["vs-second","1.58.0","ewewew","ewewew"]
["vs-third","1.42.0","ewewew","ewewe"]
["vs-fourth","1.58.0","eewfwfef","vvfffsfsf"]
["vs-fifth","1.39.0","fvrvvsdvds","vvsvdsvds"]

或者等效地,重构出重复的.value 查找:

jq -c '.streams | to_entries[] | [.key, (.value | .version, .branch, .hash)]' vs.json
["vs-first","2.33.0","ewewew","ewewewewe"]
["vs-second","1.58.0","ewewew","ewewew"]
["vs-third","1.42.0","ewewew","ewewe"]
["vs-fourth","1.58.0","eewfwfef","vvfffsfsf"]
["vs-fifth","1.39.0","fvrvvsdvds","vvsvdsvds"]

添加 bash 处理

jq 不能做所有事情,所以如果你确实想将结果输出到 bash 以进行额外的处理——例如,调用 curl——你可以使用 -r 在单独的行上打印每个值并使用 @987654338 @ 将行读入变量。它看起来像这样:

jq -r '.streams | to_entries[] | .key, (.value | .version, .branch, .hash)' vs.json |
    while read -r key &&
          read -r version &&
          read -r branch &&
          read -r hash
    do
        ...
    done

【讨论】:

  • 我还需要访问字典的键。有没有办法可以将它添加到第二个示例中?即:jq -c '.streams[] | [.key, .version, .branch, .hash]' vs.json 另外,为了更清楚,我修改了我的问题,以及为什么我需要拆分它。我需要访问密钥并获取数据。其中一个键是静态实现的,其他的都是一样的
  • 另外,第二种实现只是一个只有一个值的数组
  • 好的。这很有意义,jq -c '.streams | to_entries[] | [.key, .value.version, .value.branch, .value.hash]' vs.json 但是,每条记录只有一个元素。即:如果我这样做 $item0{0} 它会给我["vs-first","2.33.0","ewewew","ewewewewe"] 而不是vs-first
  • 再问一个问题? 如果widgets 键中有值,则最后一项是唯一读取的内容。即:在上面的示例 JSON 中,当我使用 bash 处理时,只读取了 4 个。我也尝试使用 read -a 小部件来读取它,并且 read -r 也是如此。
猜你喜欢
  • 2022-07-28
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2016-12-06
  • 2017-11-20
相关资源
最近更新 更多