我正在尝试从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
有效。但我不明白为什么。你能解释为什么一种方法正常工作而另一种方法不起作用?
答案 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
将该字符序列视为命令,并将特殊含义重新分配给\
。
答案 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)