【问题标题】:Extract values from JSON objects and assign them to shell variables in a loop从 JSON 对象中提取值并在循环中将它们分配给 shell 变量
【发布时间】:2023-03-23 15:40:01
【问题描述】:

我正在使用jq 来解析一个 json 文件 -

json 文件看起来像 -

{
  "values": [
    {
      "email": "user1@domain.com",
      "id": "USER1_ID"
    },{
      "email": "user2@domain.com",
      "id": "USER2_ID"
    },
    .
]
}

我可以打印/遍历下面的 id

for k in $(cat input.json | jq .values | jq .[].id); do
    echo $k
done

这会按预期打印每个单独的 id。

但是,我想要的是在循环中同时访问电子邮件和 id。

我尝试将值分配给 SHELL 变量,如下所示 -

emails=$(cat input.json | jq .values | jq .[].email)
ids=$(cat input.json | jq .values | jq .[].id)

这在大多数情况下都可以工作,但ids 也可以有空格,这打破了这一点。

我基本上可以有 2 个循环,一个用于 email,另一个用于 id,并在循环中为数组赋值

   i=0
    for k in $(cat input.json | jq .values | jq .[].id); do
            ids[$i]=$k
            i=$(($i +1)) 
        done

i=0
for k in $(cat input.json | jq .values | jq .[].email); do
        emails[$i]=$k
        i=$(($i +1)) 
    done

一旦我拥有数组中的两个值,我就可以并行遍历它们。

我不是 shell 专家,所以我想知道是否有任何巧妙的方法可以用更少的循环/代码行来做到这一点。

感谢您的帮助!

【问题讨论】:

  • 顺便说一句,cat foo | anything 总是更好地替换为anything <foo,或者当程序支持它时,anything foo。其中任何一个都为anything 提供了foo 上的直接文件句柄,因此它可以四处寻找、乱序读取等;这让sort 分成不同的线程来并行读取和排序文件的不同部分,或者tail 直接跳到最后等等。相比之下,cat 只按顺序从前到后读取,没有能力跳过。
  • ...而for anything in $(...) 本身就是有缺陷的; bash 和 zsh 之间存在一些差异,但大部分 BashPitfalls #1 都适用。

标签: bash shell zsh jq


【解决方案1】:

您可以将每个电子邮件 ID 对作为逗号分隔的列表从 JQ 中输出,并在 while 循环中将它们读入变量,如下所示:

while IFS=',' read -r email id; do
  echo "$email"
  echo "$id"
done <<EOF
$(jq -r '.values[] | "\(.email),\(.id)"' file)
EOF

【讨论】:

    【解决方案2】:

    假设变量没有嵌入回车,您可以通过为每个变量使用单独的read 命令来为自己节省很多 IFS 悲伤,例如:

    jq -r '.values[] | (.email, .id)'  input.json |
    while IFS= read -r email ; do
        IFS= read -r id 
        echo "email=$email and id=$id"
    done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-26
      相关资源
      最近更新 更多