Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 替换属性文件中的环境变量_Linux - Fatal编程技术网

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

Linux 替换属性文件中的环境变量,linux,Linux,在Linux中,假设我有以下文件(例如conf.properties): 我想创建另一个替换了所有环境变量的文件…例如。假设环境变量$HOSTNAME为'myhost',且未设置$unconfigured,则脚本应生成以下输出: HOST_URL=http://myhost STD_CONFIG=http://myhost/config USER_CONFIG=http://myhost/config/ 我原以为这可以用简单的一行代码和某种sed/awk魔术来完成,但我不是专家,我的搜索一直在

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

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

HOST_URL=http://myhost
STD_CONFIG=http://myhost/config
USER_CONFIG=http://myhost/config/
我原以为这可以用简单的一行代码和某种sed/awk魔术来完成,但我不是专家,我的搜索一直在进行中,所以感谢您的帮助

编辑:

我应该提到,该文件实际上可以是任何格式的文本文件,例如xml。我只想用环境中当前设置的内容替换任何看起来像env变量的内容。

我会这样做:

# 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
更新: 根据您问题中的更新,这不是一个好的解决方案

更新2: 这是基于一个假设。我已经尝试过(我不熟悉perl)删除未定义的变量

perl -p -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : $&/eg; s/\$\{([^}]+)\}//eg' yourfile.txt
应该适用于任何输入文本文件,但是您需要使用简化字符串匹配的
${…}
格式定义变量


(关于eval邪恶的咆哮移到了a,以免混淆读者)

多亏了@DarkDust,我想出了这个:

cat somefile | while read line; do echo $(eval echo `echo $line`); done > somefile.replaced
“eval是邪恶的”

这不是一个答案,而是一个警告。你真的不想那样做

附件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)
毫无戒心的用户:

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)
注意最后一行


现在,想象一下可能的情况……

我使用此oneliner替换文件中的
${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
…感受挑战!;)在三分之一的长度内完成这项工作

这里有一个简短的单行程序,它使用python的大括号格式来安全地完成这项任务:

contents=\"\"\"`cat $file`\"\"\"; python -c "import os;print $contents.format(**os.environ)"
  • 避邪
  • 允许输出花括号:使用
    {{
    而不是
    {
  • 调用脚本时无需显式指定变量
例如,给定的属性文件
设置.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}

这里有一个脚本:

这就是
envsubst
的作用

echo 'Hello $USER'
Hello $USER
echo 'Hello $USER' | envsubst
Hello malvineous
不过,您可能会更像这样使用它:

envsubst < input.txt > output.txt
envsubtoutput.txt

envsubst
似乎是GNU gettext的一部分。

下面是一段Javascript代码,我想用它来解决这个问题:

// 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`);
});

希望这对其他人有所帮助。

如果您安装了nodejs,则可以运行

npx@utft/tt-e FOO=bar/path/to/input/path/to/output
或者您可以通过编程方式运行它

我不能假设该文件是有效的shell脚本(仅名称=值)-它可能是任何格式,例如xml。@Andy Whitfield:太糟糕了:-)然后您就转到awk/sed。您的编辑给了我一个想法:这个小金块:
在读取行时cat somefile;do echo$(eval echo
echo$line
);done
此处的注释格式不太好,因此我将粘贴它作为参考答案。或更具可读性(IMHO):
sed-e's/$HOSTNAME/myhost/'-e's/$unconfigured/
…假设我知道配置文件中使用的env变量,我可以使用这种技术,但我确实需要更通用的方法。@Shawn Chin谢谢!我可能会使用它,因为我喜欢
${
使用属性的风格。我认为perl命令可以简化为
perl-p-e的/\$\{([^}]+)\}/defined$ENV{$1}?$ENV{$1}:“/eg”yourfile.txt
,根据对相关问题的评论,而不是使用第二个正则表达式来删除空变量。您只需将
$&
替换为
@JoelPearson的正则表达式具有不删除反斜杠甚至一行的优点;-)现在看来这是一个解决方案,只要您知道您的输入文件除了变量之外将不会有
$
。请不要使用它。请原谅提高声音,但这是一种需要尖叫的情况。请参阅我的ans中的解释wer.@Shawn没问题-谢谢你的警告。我使用perl行-效果很好。我更担心将来可能遇到的毫无戒心的用户。将警告作为一个单独的项目发布,以免引起混淆。这将省略行开头的空格以及包含
#
的行。这让我想起了t哦。我很惊讶人们会这么认为。bash中应该有一个替换机制,真的!否则,我们应该为此编写一个标准工具。这并不能避免邪恶的评估,它只是混淆了它。
echo';print“任意代码执行”;““>~/myfile;
创建一个文件,该文件会导致对一些任意代码进行求值。这似乎是这里唯一真正正确的答案。应该标记得更高。我只想对这个答案表示感谢。我和我的朋友正在与sed、awk和其他“技巧”作斗争这个答案拯救了我们。知识就是力量。谢谢!你应该考虑接受正确的答案。
// 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`);
});