这样做的明显方法有很多问题:
# 这会因为某些输入而失败。 HTML肯定是个问题,因为'<'和'>'字符将被解释为文件重定向
$ while read r; do eval echo $r; done < input
以下perl应该对于简单的输入可以很好地处理问题。
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ }' input
但它没有处理像${FOO-bar}这样的结构。如果您需要处理这种结构,可以转义所有shell元字符并执行while/read循环:
$ sed -e 's/\([<>&|();]\)/\\\1/g' input | while read -r l; do eval echo "$l"; done
请注意,这既不牢靠也不安全。考虑一下如下输入会发生什么:
\; rm -rf /
我说“考虑一下”。不要测试它。sed将在分号前插入反斜杠,eval将得到字符串“\\;”,这将被解释为一个反斜杠后跟一个分号,该分号终止echo,然后执行rm -rf。鉴于评估未知输入的不安全性,最好还是坚持使用像perl这样的东西,并明确替换所需的sh构造。例如:
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ };
s/\${[^-]*-([^}]*)}/$1/g' input
这个在处理${FOO=some-text}这样的输入时会有问题。为了可靠地获取所有sh结构(其中“:”可以是“-”、“?”、“=”、“+”、“%”、“#”或任何具有冒号前缀的相同符号(或者如果允许非posix sh语法,则可以是很多其他符号!)),您必须构建一组相当复杂的比较。
echo \
cat /tmp/home``会起作用吗? - Beta