将参数传递给jq过滤器

68

这是我的config.json文件:

{
    "env": "dev",
    "dev": {
        "projects" : {
            "prj1": {
                "dependencies": {},
                "description": ""
            }
        }
    }
}

这里是我的Bash命令:

PRJNAME='prj1'

echo $PRJNAME

jq --arg v "$PRJNAME" '.dev.projects."$v"' config.json 
jq '.dev.projects.prj1' config.json 

输出:

prj1
null
{
  "dependencies": {},
  "description": ""
}

所以$PRJNAME是prj1,但第一次调用只输出null

有人可以帮我吗?


1
你尝试过移除 $v 周围的 " 吗?为什么不使用 shell 来填充变量,像这样 jq ".dev.projects.$PRJNAME" config.json - Rambo Ramon
1
@RamboRamon,使用shell填充变量容易出错--考虑一下它是否包含需要转义的引号等字符。jq保证生成语法上有效的输出。 - Charles Duffy
5个回答

98

在您的示例中,jq程序.dev.projects."$v"会字面上尝试查找名为"$v"的键。请改用以下方法:

jq --arg v "$PRJNAME" '.dev.projects[$v]' config.json 

如果我想传递2个或更多的参数怎么办? 你能给我展示一个例子吗? - lisi4ok
17
您可以通过多次使用 --arg 指令来传递多个参数,例如:jq --arg foo 1 --arg bar 2 -n '[$foo, $bar]'。请注意,该命令会将参数值包含在方括号内以创建 JSON 数组。 - user3899165
1
能否在参数中传递多个组件?例如 PRJNAME='.dev.projects.prj1' jq --arg v "$PRJNAME" '[$v]' config.json。当然,这段代码不起作用 - 它将参数转换为由方括号包围的字符串,所以我猜测它不喜欢点符号表示法... - lane
2
从[$v]中删除''。 - datacruncher

36

当您制作 JSON 时,您也可以使用 --argjson

--arg a v       # set variable $a to value <v>;
--argjson a v   # set variable $a to JSON value <v>;

15
在传递数字或布尔值时,如果您不希望其被引号包裹,请使用argjson - Tom

21

如上方评论中所要求的,有一种方法可以传递多个参数。

也许还有更优雅的方式,但这种方法是有效的。

  • 如果您确定始终需要所有键,则可以使用以下方法:
jq --arg key1 $k1 --arg key2 $k2 --arg key3 $k3 --arg key4 $k4 '.[$key1] | .[$key2] | .[$key3] | .[$key4] '

如果该键不总是被使用,您可以这样做:
jq --arg key $k ' if key != "" then .[$key] else . end'

  • 如果key有时指向一个数组:
jq --arg key $k ' if type == "array" then .[$key |tonumber] else .[$key] end'

当然可以将它们结合在一起!

1
这仅适用于一个变量,当我尝试两个变量时它会失败: OUTPUT=$(cat test.json | jq --arg env $ENV --arg app $APP '.[$env] .apps .[$app] .bar') - Broshi
[$key | tonumber] 对我很有帮助,谢谢! - Ignacio Tomas Crespo

5

你可以这样做:


    key="dev.projects.prj1"
    filter=".$key"
    cat config.json | jq $filter


或者 jq $(echo ".$some_var") 可以成为一行代码 :) 感谢 @Z.San 提供如此好的想法! - Nícolas Schirmer

0

我的示例bash命令用于替换JSON文件中的数组。所有内容都在变量中:

a=/opt/terminal/conf/config.json ; \
b='["alchohol"]' ; \
c=terminal.canceledInspections.resultSendReasons ; \
cat $a | jq .$c ; \
cat $a | jq --argjson b $b --arg c $c 'getpath($c / ".") = $b' | sponge $a ; \
cat $a | jq .$c

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接