如何在Ruby中为终端转义字符串?

32

我正试图启动mplayer。我的文件名包含空格,这些空格应该被转义。

这是我正在使用的代码:

@player_pid = fork do
   exec "/usr/bin/mplayer #{song.file}"
end

如果#{song.file}包含类似"/home/example/music/01 - a song.mp3"这样的路径,我该如何适当地转义这个变量(以及标题可能包含的其他奇怪字符),以便终端接受我的命令?

2个回答

51

Shellwords 应该适合您 :)

exec "/usr/bin/mplayer %s" % Shellwords.escape(song.file)
在 Ruby 1.9.x 中,看起来你必须先require它。
require "shellwords"

但在 Ruby 2.0.x 中,我不必显式地要求它。


22

请永远不要使用 "单行命令" 形式的 exec,那会让你面临所有通常的引号和注入问题,并且毫无意义地启动一个 shell。从fine manual中可以看到:

exec(cmdname, arg1, ...)

命令名称和一个或多个参数(没有 shell)

因此,与其折腾引号和转义等问题,不如直接使用无 shell 版本:

exec '/usr/bin/mplayer', song.file

并且完全绕过shell。同样适用于system


1
这里的难点在于并非每个人都有/usr/bin/mplayer路径,因此您可能需要引用一种机制来定位可执行文件。当然,如果这个程序只是供您自己使用,那就没问题了。 - vgoff
这个解决方案确实也可以,但由于我的问题实际上是关于如何转义字符串的,所以我将保持我的答案不变,谢谢。 - xorinzor
是的,但当您指定路径时,您会失去这个好处,这就是您的示例形成的方式。这就是为什么我提到它的原因。 - vgoff
1
就这个问题而言,“/usr/bin/env mplayer” 是从$PATH中运行二进制文件的标准方式。 - chutz

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