首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何获取所有值并使用脚本参数

如何获取所有值并使用脚本参数
EN

Stack Overflow用户
提问于 2016-02-01 22:20:47
回答 4查看 2.4K关注 0票数 4

我有这个vms.json

代码语言:javascript
复制
[
    {
        "name": "jms1",
        "port1": 24000,
        "port2": 25000,
        "port3": 26000
    },

    {
        "name": "jms2",
        "port1": 24001,
        "port2": 25000,
        "port3": 26001
    }
]

我有一个port_script.sh,它以名称port2作为编号参数。

我可以运行这个jq来获取密钥,但是我需要得到值。

代码语言:javascript
复制
jq -r -c '.[] |keys' vms.json
["port1","name","port2","port3"]
["port1","name","port2","port3"]

我不知道如何使用这个输出来获得相关的值。如果我能得到这些值,我应该能够通过xargs将它们输送到我的脚本中。

提前感谢您的帮助

添加: port_script.sh

代码语言:javascript
复制
#!/bin/bash
name=$1
port1=$2
port2=$3
port3=$4
vagrant ssh ${name} -- \
    -L ${port1}:127.0.0.1:${port1}  \
    -R ${port2}:127.0.0.1:${port2}  \
    -L ${port3}:127.0.0.1:${port3} 

应用圣地亚哥和匹克的回应-这对我有用

代码语言:javascript
复制
eval "$(jq -r '.[] | ["./port_script.sh"] + [.name, .port1, .port2, .port3 | @sh] | join(" ")' vms.json)"
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-02-02 04:32:27

让圣地亚哥的回答更进一步,你可以写:

代码语言:javascript
复制
$ jq -r '.[] | "port_script.sh \"\(.name)\" \"\(.port1)\" \"\(.port2)\" \"\(.port3)\""'

通过您的输入,这将产生:

代码语言:javascript
复制
port_script.sh "jms1" "24000" "25000" "26000"
port_script.sh "jms2" "24001" "25000" "26001"

或许更好的是:

代码语言:javascript
复制
$ jq -r --arg command port_script.sh '.[] 
  | $command + " \"\(.name)\" \"\(.port1)\" \"\(.port2)\" \"\(.port3)\""'

如果每个对象中的键按照脚本所需的顺序排列,那么我们可以进一步概括,以便jq脚本可以对任意数量的键工作:

代码语言:javascript
复制
jq -nr --arg command port_script.sh '
  .[] | $command + " " + ([.[]] | @sh)'

port_script.sh 'jms1' 24000 25000 26000
port_script.sh 'jms2' 24001 25000 26001

(不幸的是,jq没有system子命令,至少现在还没有。)

票数 3
EN

Stack Overflow用户

发布于 2016-02-01 23:22:02

您试图尝试的内容非常不清楚,但以下是一些可能有帮助的提示:

要获得脚本所需的值,只需使用.foo语法引用它们。例如,在给定的输入文件上运行jq -r '.[].name'将产生以下输出:

代码语言:javascript
复制
jms1
jms2

同样,您也可以引用所有这些内容:

jq -r '.[] | .name, .port1, .port2, .port3'

代码语言:javascript
复制
jms1
24000
25000
26000
jms2
24001
25000
26001

而且,如果您想要像上面的示例那样将它们放在数组中,只需将它们放在括号中:

jq -r -c '.[] | [.name, .port1, .port2, .port3]'

代码语言:javascript
复制
["jms1", 24000, 25000, 26000]
["jms2", 24001, 25000, 26001]

希望这能有所帮助!这是我在没有真正理解你的问题的情况下所能做的。

票数 1
EN

Stack Overflow用户

发布于 2020-10-27 15:11:21

最近我不得不处理这个问题,因为我被要求在shell脚本中使用json。

因此,对于将来发现这个话题的人来说:

我建议使用一种更自然的shell方法,而不是使用eval函数。

考虑使用循环和read命令。

代码语言:javascript
复制
#!/bin/bash
read -d '' JSON <<'EOF' || true
[
    {
        "name": "jms1",
        "port1": 24000,
        "port2": 25000,
        "port3": 26000
    },

    {
        "name": "jms2",
        "port1": 24001,
        "port2": 25000,
        "port3": 26001
    }
]
EOF

while IFS=$'\t' read name port1 port2 port3 eol ; do

    ./port_script.sh "$name" "$port1" "$port2" "$port3"

done <<<" $(echo "$JSON" | jq --raw-output '.[] | [.name, .port1, .port2, .port3] | @tsv' )"

注:

如果通过desgin,您的JSON可以包含空字段,这可能是一个问题。jq的@tsv函数工作正常,并用制表符分隔所有东西。但至少Bash会将多个分隔符视为一个。只有当您使用空白空间(“”或"\t")作为分隔符时,这才是正确的。我用以下方法解决了这个问题:

代码语言:javascript
复制
$(echo "$JSON" | jq --raw-output '.[] | [.name, .port1, .port2, .port3] | @tsv' | tr $'\011' $'\037' )  

这将用ASCII单元分隔器(八进制037)取代所有选项卡(八进制011)。

我首先尝试将'\t\t‘替换为'\tspace\t’,这会很好,因为当您将多个空格用作port_script.sh的参数时,多个空格将再次缩减为一个.但是这会抛出任何条件测试(例如,测试-z )。

该单元分离器应该是安全的使用这一点。如果jq能直接实现这一点就好了..。但是的:)

并将其更改为while循环:

代码语言:javascript
复制
...
while IFS=$'\037' read name port1 port2 port3 eol ; do
...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35141521

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档