【问题标题】:jq: iterate over every element of list and replace it with valuejq:遍历列表的每个元素并将其替换为值
【发布时间】:2021-05-18 06:32:18
【问题描述】:

我有这个 json 文件:

{
  "name": "market",
  "type": "grocery",
  "shelves": {
    "upper_one": [
      "23423565",
      "23552352",
      "08789089"
    ]
  }
}

我需要遍历列表的每个元素(upper_one),并将其替换为其他值。


我试过这段代码:

#/bin/bash

for product in $(cat first-shop.json| jq -r '.shelves.upper_one[]')
do
  cat first-shop.json| jq --arg id "$((1 + $RANDOM % 10))" --arg product "$product" -r '.shelves.upper_one[]|select(. == $product)|= $id' 
done

但是我得到了这样的输出:

1
23552352
08789089
23423565
10
08789089
23423565
23552352
7

是否可以用 jq 迭代列表,用另一个函数的值替换值(如代码中的 $id),并用替换值打印整个最终 json?


我需要这种输出:

{
  "name": "market",
  "type": "grocery",
  "shelves": {
    "upper_one": [
      "1",
      "10",
      "7"
    ]
  }
}

不仅仅是“upper_one”列表三次的元素。

【问题讨论】:

  • 你想用什么替换它们?随机数?
  • 不,我在脚本中有另一个函数,可以生成我需要的文本。这只是一个例子。
  • 你能展示你的脚本的示例输出吗?例如,它是否已经有 json 引号?
  • @Aserre 示例输出位于“但我得到了这种输出:”部分
  • 我的意思是当你说I have another function in the script, that would generate the text I need。只是生成文本,还是正确的 json(带引号)?

标签: bash jq


【解决方案1】:

你可以试试下面的脚本:

#!/usr/bin/env bash

for product in $(jq -r '.shelves.upper_one[]' input.json)
do
    id="$((1 + $RANDOM % 10))"
    newIds+=("$id")
done

jq  '.shelves.upper_one = $ARGS.positional' input.json --args "${newIds[@]}"

【讨论】:

  • 太棒了!但是第一个元素将是一个空字符串,因为newIds=("${newIds[@]}" "$id")中的“$id”前面有空格,用newIds+=("$id")替换它可以解决这个问题。
  • @star 确实!不错的收获
【解决方案2】:

恕我直言,最好使用一些脚本语言并以编程方式操作对象。如果 bash 和 jq 是您唯一的选择 - 虽然不是很好,但可以完成这项工作

$ jq '.shelves.upper_one[] |= (sub("23423565";"1") | sub("23552352";"10") | sub("08789089";"7"))' your.json
{
  "name": "market",
  "type": "grocery",
  "shelves": {
    "upper_one": [
      "1",
      "10",
      "7"
    ]
  }
}

考虑使用| tonumber 转换为数字

【讨论】:

  • 但是我需要改变它不是用静态数字,而是我从另一个函数得到的数字——这是主要的麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-06
  • 2019-02-03
  • 2013-04-08
  • 2018-03-14
  • 2023-03-18
  • 2018-12-14
  • 1970-01-01
相关资源
最近更新 更多