替换属性文件中的环境变量

时间:2011-03-11 14:45:17

标签: linux

在Linux中,说我有以下文件(例如conf.properties):

HOST_URL=http://$HOSTNAME
STD_CONFIG=http://$HOSTNAME/config
USER_CONFIG=http://$HOSTNAME/config/$unconfigured

我想创建另一个替换了所有环境变量的文件...例如。假设环境变量$ HOSTNAME是'myhost'并且未设置$ unconfigured,脚本应该产生以下输出:

HOST_URL=http://myhost
STD_CONFIG=http://myhost/config
USER_CONFIG=http://myhost/config/

我当时认为这可以通过一个简单的单行程来完成,并带有某种sed / awk魔法,但我不是专家,而且我的搜索一直是静止的,所以感谢任何帮助。

编辑:

我应该提一下,该文件可以是任何格式文本文件,例如xml。我只想用环境中当前设置的任何东西来替换任何看起来像env变量的东西。

9 个答案:

答案 0 :(得分:115)

这是envsubst的用途。

echo 'Hello $USER'
Hello $USER
echo 'Hello $USER' | envsubst
Hello malvineous

你可能会更喜欢这样使用它:

envsubst < input.txt > output.txt

envsubst似乎是GNU gettext的一部分。

答案 1 :(得分:8)

sed 's/$HOSTNAME/myhost/g;s/$unconfigured//g' yourfile.txt > another_file.txt

更新

根据您问题的更新,这不是一个好的解决方案。

update2:

这基于answer to a related question。我已经攻击它(我不熟悉perl)来移除未定义的变量。

perl -p -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : $&/eg; s/\$\{([^}]+)\}//eg' yourfile.txt

应该适用于任何输入文本文件,但是您需要使用${...}格式定义变量,这样可以简化字符串匹配。

关于eval邪恶的咆哮感动了separate post,以免混淆读者

答案 2 :(得分:6)

“eval是邪恶的”

这不是答案,而是针对using eval for this task的警告。你真的真的不想这样做。

图表1:恶意模板文件:

HOST_URL=http://$HOSTNAME
STD_CONFIG=http://$HOSTNAME/config
USER_CONFIG=http://$HOSTNAME/config/$unconfigured
&& cat /etc/redhat-release

毫无疑问的用户:

[lsc@aphek]$ cat somefile | while read line; do echo $(eval echo `echo $line`); done
HOST_URL=http://xyz
STD_CONFIG=http://xyz/config
USER_CONFIG=http://xyz/config/
Red Hat Enterprise Linux WS release 4 (Nahant Update 9)

请注意最后一行!

现在,想象一下可能性......

答案 3 :(得分:5)

我会这样做:

# Set the $HOSTNAME and other variables
# Now evaluate the properties file as a shell script.
. config.properties
# Write the values
cat >somefile <<EOF
HOST_URL=$HOST_URL
STD_CONFIG=$STD_CONFIG
USER_CONFIG=$USER_CONFIG
EOF

编辑:或者这个非常讨厌的事情(我确信有更好的方法)

for name in HOST_URL STD_CONFIG USER_CONFIG
    echo "$name=$(eval echo `echo '$'$name`)" >>somefile
end

答案 4 :(得分:2)

感谢@DarkDust,我想出了这个:

cat somefile | while read line; do echo $(eval echo `echo $line`); done > somefile.replaced

答案 5 :(得分:2)

我使用这一个衬垫来替换文件中的${VARIABLE}样式变量:

TARGET_FILE=/etc/apache2/apache2.conf; for VARNAME in $(grep -P -o -e '\$\{\S+\}' ${TARGET_FILE} | sed -e 's|^\${||g' -e 's|}$||g' | sort -u); do sed -i "s|\${$(echo $VARNAME)}|${!VARNAME}|g" ${TARGET_FILE}; done

我很确定有人可以使用awk以1/3的长度做到这一点...感到挑战! ;)

答案 6 :(得分:1)

这是我喜欢用来解决这个确切问题的一小段Java代码:

// A Javascript version of envsubst for our builds
// Purpose: replace all ocurrences of ${VAR} with the equivalent var from the environment from stdin
var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

const environment = process.env;

rl.on('line', function(line) {
  const newLine = line.replace(/\$\{([a-zA-Z0-9_]+)\}/g, function(_match, variable) {
    const envVar = environment[variable];
    return envVar ? envVar : '';
  });

  process.stdout.write(`${newLine}\n`);
});

希望这对其他人有帮助。

答案 7 :(得分:0)

这是一个简短的单行程序,使用python的大括号格式来安全地完成魔术:

contents=\"\"\"`cat $file`\"\"\"; python -c "import os;print $contents.format(**os.environ)"
  • 避免邪恶的评估
  • 允许输出花括号:使用{{代替{
  • 调用脚本时无需明确指定变量

例如,给定属性文件settings.properties

# my properties file
someVar = {MY_ENV_VAR}
curlyBraceVar = has {{curly braces}}

然后,用:

进行替换
$ export MY_ENV_VAR="hello"
$ file=settings.properties 
$ contents=\"\"\"`cat $file`\"\"\"; python  -c "import os;print $contents.format(**os.environ)"
# my properties file
someVar = hello
curlyBraceVar = has {curly braces}

脚本在这里:https://raw.githubusercontent.com/aneilbaboo/machome/master/bin/substenv

答案 8 :(得分:0)

如果已安装nodejs,则可以运行

npx @utft/tt -e FOO=bar /path/to/input /path/to/output

或者您可以通过编程方式运行它 https://github.com/utftufutukgyftryidytftuv/tt