用它们的实际值替换文件中的环境变量?

Rob*_*ser 77 scripting shell-script text-processing environment-variables

有没有一种简单的方法来替换/评估文件中的环境变量?假设我有一个config.xml包含以下内容的文件:

<property>
    <name>instanceId</name>
    <value>$INSTANCE_ID</value>
</property>
<property>
    <name>rootPath</name>
    <value>/services/$SERVICE_NAME</value>
</property>
Run Code Online (Sandbox Code Playgroud)

...等等。我想$INSTANCE_IDINSTANCE_ID环境变量的值替换文件$SERVICE_NAME中的SERVICE_NAMEenv var的值。我不会先验地知道需要哪些环境变量(或者,如果有人向配置文件添加了新的环境变量,我不想更新脚本)。谢谢!

don*_*sti 119

您可以使用envsubst(部分gnu gettext):

envsubst < infile
Run Code Online (Sandbox Code Playgroud)

会将文件中的环境变量替换为其相应的值。变量名称必须仅由字母数字或下划线 ASCII 字符组成,不能以数字开头且非空;否则这样的变量引用将被忽略。


要仅替换某些环境变量,请参阅此问题。

  • 那挺好的。Docker 镜像应该是轻量级和量身定制的。当然,您始终可以向其中添加 envsubst。 (5认同)
  • ...除了默认情况下它没有安装在我的 docker 镜像中:'-( (3认同)
  • 请注意,它不会替换“所有”环境变量,只会替换名称与 POSIX 语言环境中的 `^[[:alpha:]_][[:alnum:]_]*$` 匹配的变量。 (2认同)

hsc*_*hou 38

这不是很好,但它有效

( echo "cat <<EOF" ; cat config.xml ; echo EOF ) | sh
Run Code Online (Sandbox Code Playgroud)

如果它在 shell 脚本中,它看起来像:

#! /bin/sh
cat <<EOF
<property>
    <name>instanceId</name>
    <value>$INSTANCE_ID</value>
</property>
EOF
Run Code Online (Sandbox Code Playgroud)

编辑,第二个建议:

eval "echo \"$(cat config.xml)\""
Run Code Online (Sandbox Code Playgroud)

编辑,与问题不严格相关,但在从文件读取变量的情况下:

(. .env && eval "echo \"$(cat config.xml)\"")
Run Code Online (Sandbox Code Playgroud)

  • 尝试在文件中放入类似 `"; ls ;"` 的内容,然后再次执行 `eval` 命令:) 这与 SQL 注入攻击的问题几乎相同。在将数据与代码混合时,您必须非常小心(这就是 shell 命令),除非您 _really_、__really__ 确定没有人试图做任何事情来扰乱您的一天。 (3认同)
  • @hschou 我认为 ilkkachu 的意思是 `\`"; ls ;"\`` - 注释格式吃了反引号。但实际上,这里应该只是`\`ls\`。关键是文件的内容会导致任意代码执行,而您对此无能为力。 (3认同)

ilk*_*chu 9

如果您碰巧有 Perl(但没有 gettext 和envsubst),您可以用一个简短的脚本进行简单的替换:

$ export INSTANCE_ID=foo; export SERVICE_NAME=bar;
$ perl -pe 's/\$([_A-Z]+)/$ENV{$1}/g'  < config.xml
<property>
    <name>instanceId</name>
    <value>foo</value>
</property>
<property>
    <name>rootPath</name>
    <value>/services/bar</value>
</property>
Run Code Online (Sandbox Code Playgroud)

我假设变量名只有大写字母和下划线,但第一个模式应该很容易根据需要进行更改。 $ENV{...}引用 Perl 看到的环境。

如果要支持${...}语法或在未设置的变量上引发错误,则需要做更多工作。gettext's 的近似等价物envsubst是:

perl -pe 's/\$(\{)?([a-zA-Z_]\w*)(?(1)\})/$ENV{$2}/g'
Run Code Online (Sandbox Code Playgroud)

虽然我觉得通过流程环境提供这样的变量一般来说似乎有点不确定:您不能在文件中使用任意变量(因为它们可能具有特殊含义),并且某些值可能至少具有半其中的敏感数据。

  • 另请参见 `perl -pe 's{\$(\{)?(\w+)(?(1)\})}{$ENV{$2} // $&amp;}ge'` 仅替换以下变量定义。 (2认同)