【问题标题】:Using jq how to pass multiple values as arguments to a function?使用 jq 如何将多个值作为参数传递给函数?
【发布时间】:2022-01-05 13:45:44
【问题描述】:

我有一个 json 文件 test.json 的内容:

[
{
  "name": "Akshay",
  "id": "234"
},
{
  "name": "Amit",
  "id": "28"
}
]

我有一个包含以下内容的 shell 脚本:

#!/bin/bash
function display
{
  echo "name is $1 and id is $2"
}

cat test.json | jq '.[].name,.[].id' | while read line; do display $line; done

我希望将单个项目的名称和 ID 作为参数一起传递给函数显示,但输出是这样的:

name is "Akshay" and id is 
name is "Amit" and id is   
name is "234" and id is 
name is "28" and id is 

实现代码的正确方法应该是什么? PS:我特别想用jq所以请根据jq来回答

【问题讨论】:

  • 您在 bash 中而不是在 jq 中实现 display 有什么原因吗?
  • @CharlesDuffy display 只是为了问这个问题,我要实现的功能不一样

标签: json linux shell jq


【解决方案1】:

两个主要问题,以及一些对您当前的示例用例可能无关紧要但在您处理来自不受信任来源的真实数据时可能很重要的附加项目:

  • 在编写 any ids 之前,您当前的代码会遍历 all names。
  • 您当前的代码使用换行符分隔符,但不会将多行读入每个 while 循环迭代。
  • 您的代码使用换行符分隔符,但换行符可以出现在字符串中;因此,这限制了输入域。
  • 当您通过管道进入while 循环时,该循环在子shell 中运行;当管道退出时,子外壳也会退出,因此循环设置的所有变量都会丢失。
  • 与让jq 直接从test.json 读取相比,启动/bin/cat 的副本并让jq 从其输出中读取管道是愚蠢且低效的。

我们可以解决所有这些问题:

  • 要成对写入names 和ids,您需要更像jq '.[] | (.name, .id)'
  • 要读取循环中每个元素的名称和 ID,您需要 while IFS= read -r name && IFS= read -r id; do ... 遍历这些对。
  • 要从换行符切换到 NUL(NUL 是唯一不能存在于 C 字符串或 bash 字符串中的字符),您需要使用 -j 参数到 jq,并且然后将显式 "\u0000" 元素添加到正在编写的内容中。要在 bash 端读取此 NUL 分隔的内容,您需要将 -d '' 参数添加到每个 read
  • 要将while read 循环移出子shell,我们可以使用process substitution,如BashFAQ #24 中所述。
  • 要让jq 直接从test.json 读取,请使用<test.json 让shell 将文件直接连接到jq 的标准输入,或者在jq 的命令行上传递文件名。

以对包含 JSON 编码 NUL 的输入数据稳健的方式执行上述所有操作,如下所示:

#!/bin/bash
display() {
  echo "name is $1 and id is $2"
}

cat >test.json <<'EOF'
[
  { "name": "Akshay", "id": "234" },
  { "name": "Amit", "id": "28" }
]
EOF

while IFS= read -r -d '' name && IFS= read -r -d '' id; do
  display "$name" "$id"
done < <(jq -j '
  def stripnuls: sub("\u0000"; "<NUL>");
  .[] | ((.name | stripnuls), "\u0000", (.id | stripnuls), "\u0000")
' <test.json)

你可以在https://replit.com/@CharlesDuffy2/BelovedForestgreenUnits#main.sh看到上面的运行

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-12
    • 2023-01-12
    • 2019-06-10
    • 1970-01-01
    • 2015-09-13
    • 2023-03-26
    • 2013-01-27
    • 1970-01-01
    相关资源
    最近更新 更多