使用Sed扩展文件中的环境变量

使用Sed扩展文件中的环境变量,sed,environment-variables,Sed,Environment Variables,我想使用Sed来扩展文件中的变量 假设我导出了一个variable=something,并有一个包含以下内容的“test”文件: I'd like to expand this: "${VARIABLE}" 我一直在尝试以下命令,但都没有用: cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile 结果是“outputfile”,变量仍然没有展开: I'd like to expand this: "$

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

假设我导出了一个variable=something,并有一个包含以下内容的“test”文件:

I'd like to expand this: "${VARIABLE}"
我一直在尝试以下命令,但都没有用:

cat test | sed -e "s/\(\${[A-Z]*}\)/`eval "echo '\1'"`/" > outputfile
结果是“outputfile”,变量仍然没有展开:

I'd like to expand this: "${VARIABLE}"
尽管如此,在bash控制台中运行
eval“echo'${VARIABLE}'
会导致值“something”被回显

期望的输出是

I'd like to expand this: "something"

有人能解释一下吗?

也许您不必使用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变量插值完成这项工作。

考虑您的试用版:

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///表示法中的字段分隔符会遇到问题。我使用了“%”,因为使用该分隔符的环境变量相对较少,但在某些机器上发现了一些包含“%”字符的环境变量,因此需要一个完整的解决方案kier.您还需要担心值中的反斜杠。您可能必须使用类似“
$(eval echo“\$$var”\124; 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
脚本是一项深奥的职业,但它说明了好工具的威力


所有这些示例都是不清理临时文件的疏忽.

这不起作用,因为在调用sed之前,shell只运行一次backticket命令替换。它的计算结果为\1,sed继续执行
的/…/\1/'
。这几乎解决了问题。我没有添加将要处理的文件中的变量是在双引号内键入的,类似于……我想这样做展开此文件:“${VARIABLE}”…在这种情况下,此序列将生成一个输出,其中变量被展开,但双引号已消失。如果测试文件包含任何更危险的内容(如:$(rm-fr$HOME)(或该文件的后引号版本),则将严重失败.的确-根本不适合受污染的输入。大约十年后,这个答案仍然很好。我特别喜欢你脚本的最后一个版本