bash 使用 jq 分配多个输出变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43291389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:59:44  来源:igfitidea点击:

using jq to assign multiple output variables

bashjqtelevision

提问by user2328273

I am trying to use jqto parse information from the TVDB api. I need to pull a couple of fields and assign the values to variables that I can continue to use in my bashscript. I know I can easily assign the output to one variable through bash with variable="$(command)"but I need the output to produce multiple variables and I don't want to make to use multiple commands.

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

I read this documentation:

我阅读了这个文档:

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

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

but I don't know if this relevant to what I am trying to do.

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

jq '.data'produces the following output:

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."
  }
]

I tried jq '.data | {episodeName:$name}'and jq '.data | .episodeName as $name'just to try and get one working. I don't understand the documentation or even if it's what I'm looking for. Is there a way to do what I am trying to do?

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

采纳答案by Bertrand Martel

You can use separate variables with read:

您可以使用单独的变量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"

Using array :

使用数组:

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]}"

Also you can split jqoutput with some character :

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

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

Or use an array like :

或者使用像这样的数组:

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

absoluteNumber, airedEpisodeNumber, episodeName& overvieware respectively ${data[0]}, ${data[1]}, ${data[2]}, ${data[3]}. set -fand set +fare used to respectively disable & enable globbing.

absoluteNumber, airedEpisodeNumber, episodeName&overview分别是${data[0]}, ${data[1]}, ${data[2]}, ${data[3]}set -fset +f分别用于禁用和启用globbing

For the jqpart, all your required fields are mapped and delimited with a '|'character with join("|")

对于jq部分,所有必填字段都被映射并用一个'|'字符分隔join("|")

If your are using jq < 1.5, you'll have to convert Number to String with tostringfor each Number fields eg:

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

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

回答by peak

jq always produces a stream of zero or more values. For example, to produce the two values corresponding to "episodeName" and "id"' you could write:

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

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

For your purposes, it might be helpful to use the -c command-line option, to ensure each JSON output value is presented on a single line. You might also want to use the -r command-line option, which removes the outermost quotation marks from each output value that is a JSON string.

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

For further variations, please see the jq FAQ https://github.com/stedolan/jq/wiki/FAQ, e.g. the question:

有关进一步的变化,请参阅 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?

问:jq 生成的 JSON 文本流如何转换为对应值的 bash 数组?

回答by agc

Experimental conversion of quoted OP input, (tv.dat), to a series of bashvariables, (and an array). The jqcode is mostly borrowed from here and there, but I don't know how to get jqto unroll an array within an array, so the sedcode does that, (that's only good for one level, but so are basharrays):

带引号的 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/)'$/)/"

Output:

输出:

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.'