【问题标题】:Using Sed to expand environment variables inside files使用 Sed 扩展文件内的环境变量
【发布时间】:2009-10-22 19:26:42
【问题描述】:

我想使用 Sed 来扩展文件中的变量。

假设我导出了一个变量 VARIABLE=something,并有一个包含以下内容的“测试”文件:

I'd like to expand this: "${VARIABLE}"

我一直在尝试以下命令,但无济于事:

cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile

结果是变量仍未展开的“输出文件”:

I'd like to expand this: "${VARIABLE}"

不过,在 bash 控制台中运行 eval "echo '${VARIABLE}' 会导致值“某物”被回显。此外,我进行了测试,该模式确实匹配。

期望的输出是

I'd like to expand this: "something"

有人能解释一下吗?

【问题讨论】:

  • 这不起作用,因为在调用 sed 之前,shell 只运行了一次反引号命令替换。它的计算结果为 \1,并且 sed 以's/..../\1/' 继续。

标签: sed environment-variables


【解决方案1】:

考虑您的试用版:

cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile

这不起作用的原因是它需要 shell 的先见之明。 sed 脚本是在 sed 匹配任何模式之前生成的,因此 shell 无法为您完成这项工作。

我过去曾以几种方式做到这一点。通常,我有一个已知变量及其值的列表,并且我已经从该列表中进行了替换:

for var in PATH VARIABLE USERNAME
do
    echo 's%${'"$var"'}%'$(eval echo "\$$var")'%g'
done > sed.script

cat test | sed -f sed.script > outputfile

如果你想任意映射变量,那么你要么需要处理整个环境(而不是变量名的固定列表,使用来自env 的输出,适当编辑),要么使用 Perl 或 Python。

请注意,如果环境变量的值在您的版本中包含斜杠,那么在 s/// 表示法中使用斜杠作为字段分隔符时会遇到问题。我使用了 '%',因为使用它的环境变量相对较少 - 但在某些机器上发现了一些确实包含 '%' 字符,因此完整的解决方案更加棘手。您还需要担心值中的反斜杠。您可能必须使用“$(eval echo "\$$var" | sed 's/[\%]/\\&/g')”之类的东西来转义环境变量值中的反斜杠和百分号。最后的问题:sed 的某些版本对脚本大小有(或有)有限的容量 - 旧版本的 HP-UX 有大约 100 个限制。我不确定这是否仍然是一个问题,但它是就在 5 年前。

对原剧本的简单改编如下:

env |
sed 's/=.*//' |
while read var
do
    echo 's%${'"$var"'}%'$(eval echo "\$$var" | sed 's/[\%]/\\&/g')'%g'
done > sed.script

cat test | sed -f sed.script > outputfile

但是,更好的解决方案是利用您已经拥有来自 env 的输出中的值这一事实,因此我们可以这样写:

env |
sed 's/[\%]/\\&/g;s/\([^=]*\)=\(.*\)/s%${\1}%\2%/' > sed.script
cat test | sed -f sed.script > outputfile

这完全安全,因为 shell 从不评估任何不应该评估的东西 - 你必须非常小心变量值中的 shell 元字符。我认为,如果env 的某些输出格式错误,此版本可能会遇到任何问题。

当心 - 用 sed 编写 sed 脚本是一项深奥的职业,但它说明了好工具的力量。

所有这些例子都没有清理临时文件。

【讨论】:

  • 大约十年后,这个答案仍然很好。我特别喜欢你脚本的最后一个版本
【解决方案2】:

也许你可以不使用 sed:

$ echo $VARIABLE
something
$ cat test
I'd like to expand this: ${VARIABLE}
$ eval "echo \"`cat test`\"" > outputfile
$ cat outputfile
I'd like to expand this: something

让shell变量插值工作。

【讨论】:

  • 这几乎解决了它。我没有添加我将工作的文件中的变量是在双引号内键入的,类似于...我想扩展这个:“${VARIABLE}”...在这种情况下,这个序列将产生一个输出,其中变量被扩展,但双引号消失了。
  • 如果测试文件包含任何更危险的东西,那将会非常失败——比如:$(rm -fr $HOME)(或反引号的版本)。
  • 确实 - 根本不适合被污染的输入。
猜你喜欢
  • 2023-03-30
  • 1970-01-01
  • 2013-06-11
  • 2021-07-15
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多