【问题标题】:Ruby escape ARGV argument or string as argument to shell commandRuby 转义 ARGV 参数或字符串作为 shell 命令的参数
【发布时间】:2011-10-18 19:02:43
【问题描述】:

好吧,这快把我逼疯了:

`ls #{"/media/music/Miles Davis"}`

因为“Miles”和“Davis”之间的空格而失败

假设我编写了一个 ruby​​ 脚本,并且用户将文件路径作为参数传递。我如何逃避它并提供给 shell-out 命令。是的,是的,我知道,应该避免炮轰。但这是一个人为的例子,我仍然需要这个。

我会做system("ls", ARGV[0]),但它不会将 ls 的 stdout 输出作为字符串返回,而这正是反引号所擅长的。

如何逃避你在 shellout 中插入的任何内容?

【问题讨论】:

    标签: ruby bash shell scripting


    【解决方案1】:

    使用require 'shellwords'Shellwords.escape,这将为您解决此类问题:

    http://apidock.com/ruby/Shellwords/shellescape

    【讨论】:

    • 太棒了!谢谢!不知道那个模块。
    • 你也可以使用快捷方式String#shellescape,像这样:ls #{"/media/music/Miles Davis".shellescape}
    【解决方案2】:

    远离构建 shell 字符串

    这是任意代码执行的一个很好的向量。

    在这种情况下,您可以使用popen,它会为您转义,例如:

    #!/usr/bin/env ruby
    IO.popen(['printf', 'a b']) do |f|
      puts f.read
    end
    

    这个输出:

    a b
    

    就像我们在终端上运行一样:

    /usr/bin/printf 'a b'
    

    如果a b 没有被转义,我们就不会像预期的那样得到a b,因为运行一个不带引号的:

    /usr/bin/printf a b
    

    在终端给出:

    a/usr/bin/printf: warning: ignoring excess arguments, starting with ‘b’
    

    在 Ubuntu 20.02、Ruby 2.6 中测试。

    【讨论】:

    • 这应该有更多的赞成票。 popen 还允许相当方便地打印出流式响应,例如。 while (line = f.gets) { puts line }.
    • 这是一个更紧凑的版本:IO.popen(["file", "--brief", "--mime-type", untrustworthy_input], in: :close, err: :close).read
    • @V-R:嗯,好的,我理解编辑。我暂时只使用这个双倍空格版本,这样用户就不必了解%q,但编辑很好。
    【解决方案3】:

    双引号也可以:

    `ls "#{'/media/music/Miles Davis'}"`
    

    `ls "#{ARGV[0]}"`
    

    【讨论】:

    • 不要那样做。考虑:a = '-l" | wc -l #"';ls "#{a}"
    • 这适用于空格,但你的字符串有一个"$ 或其他几个字符。
    猜你喜欢
    • 2012-04-16
    • 2013-02-01
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 2011-08-22
    相关资源
    最近更新 更多