我有
replace.sh
文件。想要将 #HOSTNAME
替换为实际值“mylocalhostname”。
为了实现我使用了以下命令。但无法做到。
printenv | grep "#HOSTNAME" | sed "s/#HOSTNAME/$HOSTNAME/1" | xargs export
环境变量如下所示
export HOSTNAME=mylocalhostname
export jdbc_url=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=#HOSTNAME
export jdbc_url_2=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=#HOSTNAME
export jdbc_url_3=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=#HOSTNAME
export jdbc_url_4=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=#HOSTNAME
预期输出:
#printenv
HOSTNAME=mylocalhostname
jdbc_url=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=mylocalhostname
jdbc_url_2=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=mylocalhostname
jdbc_url_3=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=mylocalhostname
jdbc_url_4=jdbc:postgresql://postgres.aws.com/dbname?ApplicationName=mylocalhostname
提前感谢您的帮助。
如何将“sed”命令输出导出到环境变量中
您必须在父 shell 中执行语句,而不是在管道内运行的子 shell 中执行语句(以及可能在
xargs
内运行以执行 export
的子 shell)。
解析
printenv
输出似乎是一个可怕的主意。只需迭代实际 bash 中的实际变量即可:
for i in "${!jdbc_url@}"; do export "$i=${!i//#HOSTNAME/$HOSTNAME}"; done
在一个完美的安全环境中,使用换行符分隔和干净的变量,您可以:
eval "$(printenv | grep "#HOSTNAME" | sed "s/#HOSTNAME/$HOSTNAME/1" | xargs -d'\n' printf "%q\n" | sed 's/^/export /')"
但是您应该使用零分隔流。我想以下内容可能还不错:
eval "$(printenv -0 | grep -z "#HOSTNAME" | sed -z "s/#HOSTNAME/$HOSTNAME/1" | xargs -z printf "%q\0" | sed -z 's/^/export /; s/$/\n/')"
推荐阅读 bash 评估和安全问题。哦,您还可以读取行,从而避免 eval 的需要:
while IFS= read -r -d '' line; do
export "$line";
done < <(printenv -0 | grep -z "#HOSTNAME" | sed -z "s/#HOSTNAME/$HOSTNAME/1")
# or
readarray -d '' -t lines < <(printenv -0 | grep -z "#HOSTNAME" | sed -z "s/#HOSTNAME/$HOSTNAME/1")
export "${lines[@]}"
请注意,
grep "#HOSTNAME" | sed "s/#HOSTNAME/$HOSTNAME/1"
等于 sed '/#HOSTNAME/!d; s//'"$HOSTNAME/1"
。
如果你的
replace.sh
文件只包含环境变量声明,你可以使用这个:
(source replace.sh; sed 's/#HOSTNAME/$HOSTNAME/; s/.*/echo "&"/e' replace.sh)