从shell脚本中的变量运行shell命令

时间:2015-02-18 09:39:21

标签: linux bash shell sed

我正在尝试从shell脚本中的变量运行命令。正在使用的shell是bash shell。

文件exp包含:

abcdef

执行以下命令:

sed s/b/\ / exp

...产生输出:

a  cdef

但执行:

cmd="sed s/b/\ / exp"
echo $cmd
$cmd

...产生以下错误:

sed s/b/\ / exp
sed: -e expression #1, char 5: unterminated `s' command

我可以看到在执行前添加eval有效。但我不明白为什么。你能解释为什么一种方法正常工作而另一种方法不起作用?

5 个答案:

答案 0 :(得分:6)

你遇到的问题是Bash没有正确解释空间本身。

如果您将b替换为其他字符,请说明它是如何运作的,例如X

$ cmd="sed s/b/X/ exp"
$ $cmd
aXcdef

所以解决方法是使用十六进制作为空格,20

$ cmd="sed s/b/\x20/ exp"
$ $cmd
a cdef

或者使用eval执行命令本身:

$ cmd="sed s/b/\ / exp"
$ eval "$cmd"
a cdef

正如Tom Fenech所建议的那样,将命令存储在变量中并不是一种好的方法,如I'm trying to put a command in a variable, but the complex cases always fail!中所述。它有时可以工作,但在其他情况下会产生不可预测的结果。另一种方法是考虑使用函数。

最后,注意eval在这样的情况下可以派上用场,只是对存储的内容非常小心。一些好的阅读:Variable as command; eval vs bash -c

答案 1 :(得分:3)

它看起来像一个引用问题:

cmd="sed s/b/\ / exp"使$cmd保留一系列没有特殊含义的字符。所以你的\无法逃脱你的空间。

eval将该字符序列视为命令,并将特殊含义重新分配给\

另请参阅:Preserving quotes in bash function parameters

答案 2 :(得分:1)

如果您需要变量中的输出,请使用

cmd=$(sed 's/b/ /' exp)

就像@thomas说的那样,如果你使用的是变量,你可以使用双引号。

答案 3 :(得分:0)

这应该做:

cmd=$(sed "s/b/\ /" exp)

以变量使用var=$(commands)

存储数据

答案 4 :(得分:0)

如果引用sed参数,脚本更容易阅读,只需要反斜杠就可以转义特殊字符(例如反斜杠和双引号):

cmd=$(sed "s/b/ /" exp)

如果使用单引号,则可以减少转义的次数 - 但是会阻止您使用这样的变量:

xxx=something
cmd=$(sed "s/b/$xxx/" exp)