使用 jq 分配多个输出变量

using jq to assign multiple output variables

我正在尝试使用 jq 来解析来自 TVDB api 的信息。我需要提取几个字段并将值分配给我可以在 bash 脚本中继续使用的变量。我知道我可以通过 bash 和 variable="$(command)" 轻松地将输出分配给一个变量,但我需要输出来产生多个变量,我不想使用多个命令。

我阅读了这份文档:

https://stedolan.github.io/jq/manual/v1.5/#Advancedfeatures

但我不知道这是否与我正在尝试做的相关。

jq '.data' 产生以下输出:

[
  {
    "absoluteNumber": 51,
    "airedEpisodeNumber": 6,
    "airedSeason": 4,
    "airedSeasonID": 680431,
    "dvdEpisodeNumber": 6,
    "dvdSeason": 4,
    "episodeName": "We Will Rise",
    "firstAired": "2017-03-15",
    "id": 5939660,
    "language": {
      "episodeName": "en",
      "overview": "en"
    },
    "lastUpdated": 1490769062,
    "overview": "Clarke and Roan must work together in hostile territory in order to deliver an invaluable asset to Abby and her team."
  }
]

我尝试了 jq '.data | {episodeName:$name}'jq '.data | .episodeName as $name' 只是为了尝试让一个工作。我不理解文档,即使它是我正在寻找的。有没有办法做我想做的事?

您可以将单独的变量与 read 一起使用:

read var1 var2 var3 < <(echo $(curl -s 'https://api.github.com/repos/torvalds/linux' | 
     jq -r '.id, .name, .full_name'))

echo "id        : $var1"
echo "name      : $var2"
echo "full_name : $var3"

使用数组:

read -a arr < <(echo $(curl -s 'https://api.github.com/repos/torvalds/linux' | 
     jq -r '.id, .name, .full_name'))

echo "id        : ${arr[0]}"
echo "name      : ${arr[1]}"
echo "full_name : ${arr[2]}"

你也可以用一些字符拆分 输出:

IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data | 
    map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] | 
    join("|")) | join("\n")')

或者使用像这样的数组:

set -f; IFS='|' data=($(curl '......' | jq -r '.data | 
    map([.absoluteNumber, .airedEpisodeNumber, .episodeName, .overview] | 
    join("|")) | join("\n")')); set +f

absoluteNumberairedEpisodeNumberepisodeNameoverview分别为${data[0]}${data[1]}${data[2]}${data[3]}set -fset +f分别用于禁用和启用globbing

对于 部分,所有必填字段都已映射并使用 '|' 字符和 join("|")

分隔

如果您使用的是 jq < 1.5,则必须为每个数字字段使用 tostring 将数字转换为字符串,例如:

IFS='|' read var1 var2 var3 var4 < <(curl '......' | jq -r '.data | 
    map([.absoluteNumber|tostring, .airedEpisodeNumber|tostring, .episodeName, .overview] | 
    join("|")) | join("\n")')

jq 总是产生零个或多个值的流。例如,要生成对应于 "episodeName" 和 "id"' 的两个值,您可以这样写:

.data[] | ( .episodeName, .id )

为了您的目的,使用 -c 命令行选项可能会有所帮助,以确保每个 JSON 输出值显示在一行中。您可能还想使用 -r 命令行选项,它会从 JSON 字符串的每个输出值中删除最外层的引号。

有关更多变化,请参阅 jq 常见问题解答 https://github.com/stedolan/jq/wiki/FAQ,例如问题:

Q: How can a stream of JSON texts produced by jq be converted into a bash array of corresponding values?

引用的 OP 输入(tv.dat)到一系列 bash 变量(和数组)的实验性转换。 jq 代码主要是从各处借来的,但我不知道如何让 jq 在数组中展开一个数组,所以 sed 代码就是这样做的,(那是仅适用于一个级别,但 bash 数组也是如此):

jq -r ".[] | to_entries | map(\"DAT_\(.key) \(.value|tostring)\") | .[]" tv.dat | 
while read a b ; do echo "${a,,}='$b'" ; done |
sed -e '/{.*}/s/"\([^"]*\)":/[]=/g;y/{},/() /' -e "s/='(/=(/;s/)'$/)/"

输出:

dat_absolutenumber='51'
dat_airedepisodenumber='6'
dat_airedseason='4'
dat_airedseasonid='680431'
dat_dvdepisodenumber='6'
dat_dvdseason='4'
dat_episodename='We Will Rise'
dat_firstaired='2017-03-15'
dat_id='5939660'
dat_language=([episodeName]="en" [overview]="en")
dat_lastupdated='1490769062'
dat_overview='Clarke and Roan must work together in hostile territory in order to deliver an invaluable asset to Abby and her team.'