我正在使用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。
答案 0 :(得分:4)
使用gnu实用程序envsubst
:
installScript=$(jq -r '.script.install' "$examplefile" | envsubst)
答案 1 :(得分:3)
请注意#!/bin/bash
examplefile="../lib/example.json"
HOST=ec2-..-...-...-...us-west-2.compute.amazonaws.com
PEMFILE=${HOME}/test.pem
export HOST
export PEMFILE
installScript=$(jq -Mr '
.script.install | gsub("(?<x>[$][{]?\\w+[}]?)"; env[.x|gsub("[${}]+";"")] )
' $examplefile)
echo $installScript
要求变量作为环境变量传递,而不是shell变量。
/home/runner/lib/install.sh ec2-..-...-...-...us-west-2.compute.amazonaws.com /home/runner/test.pem
示例输出
import java.awt.*;
import javax.swing.*;
public class Menu_Frame extends JFrame{
Menu_Panel menu_panel = new Menu_Panel();
public Menu_Frame(){
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension screenSize = kit.getScreenSize();
int screenHeight = screenSize.height;
int screenWidth = screenSize.width;
setExtendedState(JFrame.MAXIMIZED_BOTH);
setPreferredSize(new Dimension(screenWidth, screenHeight));
setLocationByPlatform(true);
getContentPane().add(menu_panel);
}
}
答案 2 :(得分:3)
这是解决所述问题的jq解决方案,但它只适用于&#34; global&#34;环境变量。
def substitute:
gsub("\\${HOME}"; env.HOME)
| gsub("\\$HOST"; env.HOST)
| gsub("\\$PEMFILE"; env.PEMFILE)
| gsub("\\$VAR1"; env.VAR1)
| gsub("\\$VAR2"; env.VAR2)
;
walk( if type=="string" then substitute else . end )
如果你的jq还没有walk/1
,请升级你的jq或snarf https://github.com/stedolan/jq/blob/master/src/builtin.jq
上面的解决方案有点脆弱,但很容易被证明或推广,如下一节所示。
walk(if type == "string"
then gsub("\\$(?<x>[A-Za-z_][A-Za-z0-9_]+)"; "\(env[.x])")
| gsub("\\${(?<x>[A-Za-z_][A-Za-z0-9_]+)}"; "\(env[.x])")
else . end)
答案 3 :(得分:0)
#!/bin/sh
TMP=$(mktemp /tmp/$$.XXX)
cat<<E_O_F > $TMP
cat <<EOF
$(cat so-dollar-variables.json)
EOF
E_O_F
. $TMP
/bin/rm "$TMP"
答案 4 :(得分:0)
我多年来一直在打这个。我想我终于得到了一个不错的纯bash解决方案:使用正则表达式匹配和间接参数替换
# read the file
json=$(< file.json)
echo step 0
echo "$json"
# set the relevant vars, just plain shell variables
HOST=_host_
PEMFILE=_pemfile_
VAR1=_var1_
VAR2=_var2_
# replace '$var' forms
while [[ $json =~ ("$"([[:alnum:]_]+)) ]]; do
json=${json//${BASH_REMATCH[1]}/${!BASH_REMATCH[2]}}
done;
echo
echo step 1
echo "$json"
# replace '${var}' forms
while [[ $json =~ ("$""{"([[:alnum:]_]+)"}") ]]; do
json=${json//${BASH_REMATCH[1]}/${!BASH_REMATCH[2]}}
done
echo
echo step 2
echo "$json"
输出
step 0
{
"script": {
"install": "${HOME}/lib/install.sh $HOST $PEMFILE",
"Setup": "${HOME}/lib/setup.sh $HOST $PEMFILE $VAR1 $VAR2"
}
}
step 1
{
"script": {
"install": "${HOME}/lib/install.sh _host_ _pemfile_",
"Setup": "${HOME}/lib/setup.sh _host_ _pemfile_ _var1_ _var2_"
}
}
step 2
{
"script": {
"install": "/home/jackman/lib/install.sh _host_ _pemfile_",
"Setup": "/home/jackman/lib/setup.sh _host_ _pemfile_ _var1_ _var2_"
}
}
神奇的是:
正则表达式,我捕获$VAR
和VAR
,以及
[[ $json =~ ("$"([[:alnum:]_]+)) ]]
# ..........1 2 21
参数替换,我在其中搜索字符串"$VAR"
并将其替换为间接变量扩展${!VAR}
${json//${BASH_REMATCH[1]}/${!BASH_REMATCH[2]}}