【发布时间】:2017-11-01 19:03:39
【问题描述】:
我正在使用 JQ 在 shell 脚本中读取 JSON。在这里,我无法即时解释我的 shell 脚本中的变量 $HOME、$HOST、$PEMFILE。
JSON 文件:
{
"script": {
"install": "${HOME}/lib/install.sh $HOST $PEMFILE",
"Setup": "${HOME}/lib/setup.sh $HOST $PEMFILE $VAR1 $VAR2"
}
}
Shell 脚本:
#!/bin/bash
examplefile="../lib/example.json"
HOST=ec2-..-...-...-...us-west-2.compute.amazonaws.com
PEMFILE=${HOME}/test.pem
installScript=($(jq '.script.install' $examplefile))
bash "$installScript"
有没有一种方法可以在不修改 JSON 的情况下即时解释这些变量?
P.S 我不想使用 eval。
【问题讨论】:
-
你应该改变 JSON;将任意命令存储为单个字符串是一个坏主意。实际上,没有正确引用要扩展的参数。
-
您还需要使用
bash -c,否则"$installScript"将被视为要执行的脚本的名称。 -
installScript=($(jq '.script.install' $examplefile))在这里是一种奇怪的形式——您将字符串结果拆分为一个数组,但是在bash "$installScript"中您只是扩展了该数组的第一个元素。并且字符串分割在手头的使用中通常是错误的——参见BashFAQ #50。 -
...也就是说 --
bash -c "$(jq -r '.script.install' "$exampleFile")"可能是你想要的。只要变量被export分配到环境中,bash的副本本身就会执行替换——无需提前这样做。 (如果您还没有导出它们,请执行此操作:export HOST PEMFILE就可以了)。 -
...oh -- 并且要明确一点:Shell 参数扩展 不完全相同 只是进行字符串替换。例如,假设你有
VAR1=$'"hello" * \' * \' $(touch /tmp/i-could-have-deleted-your-files) "world"'——如果你运行echo "$VAR1",*都不会被文件列表替换,/tmp/i-could-have-deleted-your-files也不会被创建。另一方面,如果你在将内容作为代码传递之前使用字符串替换——就像你问我们怎么做一样——替换的结果将被解析为语法。