如何强制bash对字符串进行变量扩展?

时间:2014-11-25 14:40:43

标签: bash variable-expansion

我已从该文件中读取了一行bash代码,我想将其发送到日志。为了使它更有用,我想发送该行的可变扩展版本。

我想只扩展shell变量。我不希望解释管道,也不想产生任何副流程,例如使用$( rm -r /)扩展行时。

我知道变量扩展非常深入到bash中。我希望有一种方法可以执行只是扩展,而不会产生任何副作用,这些副作用来自管道,外部程序以及 - 也许 - 这里 - 文档。

也许有类似eval的内容?

#!/bin/bash
linenr=42
line=`sed "${linenr}q;d" my-other-script.sh`
shell-expand $line >>mylog.log

我想要一种只扩展shell变量的方法。 如果x=aa="example",那么我希望进行以下扩展:

echo $x应为echo a

echo ${a}应为echo example

touch ${!x}.txt应为touch example.txt

if [ (( ${#a} - 6 )) -gt 10 ]; then echo "Too long string"应为if [ 1 -gt 10 ]; then echo "Too long string"

echo "\$a and \$x">/dev/null应为echo "\$a and \$x>dev/null"

2 个答案:

答案 0 :(得分:1)

对于五年后到达的人们,尽管这不是OP的问题的最佳答案,但对于该问题的答案如下。 Bash可以进行indirect参数扩展:

some_param=a
a=b
echo ${!some_param}
echo $BASH_VERSION
# 5.0.18(1)-release

答案 1 :(得分:0)

你是绝对正确的,使用bash是非常危险的。 实际上你的命令会遇到你的问题。

让我们详细讨论您的脚本:

#!/bin/bash
line=`sed "${42}q;d" my-other-script.sh`
shell-expand $line >>mylog.log

sed可能产生多行输出,因此使用名称line会产生误导。

然后你没有引用$ line,这可能有不明显的效果:

$ x='| grep x'
$ ls -l $x
ls: cannot access |: No such file or directory
ls: cannot access grep: No such file or directory
-rw-rw-r-- 1 foo bar 34493 Nov 19 18:51 x
$

在这种情况下,管道不会被执行,而是传递给程序ls。 如果您有不受信任的输入,则很难编写健壮的shell脚本。

使用eval是邪恶的 - 我绝不会建议使用它,尤其是出于这样的目的!

另一种方法是在perl中,迭代$ ENV数组并用env值替换所有env键。通过这种方式,您可以更好地控制可能发生的事情。