在shell脚本中从变量运行一个shell命令

7
我将尝试在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是有效的。但我无法理解为什么。你能解释一下为什么一个方法有效而另一个方法无效吗?


9
不要把命令放进字符串中。就像你所看到的,这并不总是有效的。这里有一些推荐阅读 - Tom Fenech
1
感谢您的回复和链接。 - Yosha
2
可能是重复问题:如何将所有命令参数放入一个变量中 - tripleee
2
@tripleee注意问题最终出在对sed本身的解释上。请看我的答案。 - fedorqui
5个回答

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所建议的,将命令存储在变量中不是一个好的方法,如我试图把一个命令放到一个变量中,但复杂的情况总是失败!所述。有时它可以工作,但在其他情况下可能会产生不可预测的结果。另一种选择是考虑使用函数。
最后,请注意eval在这种情况下可能很方便,只要非常小心地存储。一些不错的阅读资料:变量作为命令;eval vs bash -c

1
好的..他确实说了“bash”,但通常情况下,我不会首先向初学者介绍一个bash扩展(\x20),而不注明它不是POSIX标准。相反,转义的类型和原因应该是开始的常规位置。 - Thomas Dickey

3
看起来是引用问题: cmd="sed s/b/\ exp" 使得$cmd保存了一系列无特殊含义的字符。所以你的\不能转义空格。 eval 将该字符序列视为命令,并重新分配特殊含义给你的\
另见: 保留bash函数参数中的引号

1
如果需要将输出存储在变量中,则使用以下代码:
cmd=$(sed 's/b/ /' exp)

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


1
这与我发布的完全相同。 - Jotne
1
这和我的帖子一样。 - Jotne
3
那又怎样?在我发布答案之前,我已经开始输入答案了! - Karthikeyan.R.S
2
这个回答并没有解决原问题,原问题是关于将命令本身(而不是其输出)存储在变量中,然后对该变量执行某些操作以运行该命令。 - Tom Barron

0

如果引用sed参数,脚本会更易读,并且只需要使用反斜杠来转义特殊字符(例如反斜杠和双引号):

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

如果您使用单引号,那么就减少了更多的转义需求,但是会阻止您使用像这样的变量:

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

1
这与我发布的内容完全相同。 - Jotne
4
我们同时在编辑 - 因此我指出了一些你尚未添加到答案中的附加功能。 - Thomas Dickey
3
@Jotne 你们几乎同时发布了类似的问题。而这个至少有一些解释。我认为仅仅因为这个就给他们投反对票并不太公平。 - fedorqui
1
好像他在我解释时给我点了踩,现在没事了。 - Thomas Dickey
1
这个回答没有解决原始问题,原始问题是关于将命令本身(而不是其输出)存储在变量中,然后对该变量进行操作以运行命令。 - Tom Barron
显示剩余2条评论

0

这应该可以:

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

要将数据存储在变量中,请使用var=$(commands)


2
如果您已经回答了问题,那么其他人就不应该再发表回答了吧? - Karthikeyan.R.S
@Karthikeyan.R.S 当然每个人都可以发表自己想要的内容,但是完全和其他人重复的内容并不必要。 - Jotne
1
这个回答并没有解决原问题,原问题是想要将命令本身(而不是输出结果)存储在变量中,然后对该变量执行某些操作以运行命令。 - Tom Barron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接