5

假设我在一个变量中有一堆文本some_var,这几乎可以是任何东西。

some_var = "Hello, I'm a \"fancy\" variable | with a pipe, double- and single-quotes (terminated and unterminated), and more."

还可以说,在 CLI Ruby 应用程序中,我希望允许用户将该文本通过管道传输到任何 Unix 命令中。我允许他们输入类似some_var | espeak -a 200 -v en-us的内容,其中管道右侧的命令是安装在他们系统上的任何 unix CLI 工具。

假设我已经将变量选择和管道从它们的输入中分离出来,所以我可以 100% 确定管道后面的命令是什么。(在这种情况下,我想将变量的内容通过管道传输到espeak -a 200 -v en-us.)

我该怎么做?我认为我不能使用反引号方法或%x[]文字。我试过做以下...

system("echo '#{some_var}' | espeak -a 200 -v en-us")

...但是任何特殊字符都会搞砸,我无法删除特殊字符。我该怎么办?

4

5 回答 5

7

此外popen,您还可以查看Shellwords.escape

puts Shellwords.escape("I'm quoting many different \"''' quotes")
=> I\'m\ quoting\ many\ different\ \"\'\'\'\ quotes

这将为您引用特殊字符(bash 兼容):

system("echo '#{Shellwords.escape(some_var)}' | ....")

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html

于 2012-05-24T07:21:19.883 回答
5

哦,快乐的注射。你正在寻找 IO.popen.

IO.popen('grep ba', 'r+') {|f| # don't forget 'r+'
  f.puts("foo\nbar\nbaz\n") # you can also use #write
  f.close_write
  f.read # get the data from the pipe
}
# => "bar\nbaz\n"
于 2012-05-24T07:10:47.647 回答
5

popen并且Shellwords.escape是很好的解决方案,但系统已经内置了使用数组语法的转义

system('argument', 'argument2', 'argument3')

例如

2.1.2 :002 > abc = "freeky\nbreak"
# "freeky\nbreak" 

2.1.2 :003 > system("echo #{abc}")  #this is bad
freeky
# => true 

2.1.2 :004 > system("echo",abc)     # this is proper way
freeky
break
# => true 
于 2015-05-07T10:30:23.547 回答
0

啊哈!我找到了。根据这个页面Kernel#open实际上可以打开一个进程并将数据传递给它,而不仅仅是文件!

some_var = "Hello, I'm a \"fancy\" variable | with a pipe, double- and single-quotes (terminated and unterminated), and more."
# some_command = "espeak -a 200 -v en-us" # also works
some_command = "cat"

cmd = "|" + some_command
open(cmd, 'w+') do | subprocess |
  subprocess.write(some_var)
  subprocess.close_write
  subprocess.read.split("\n").each do |output|
    puts "[RUBY] Output: #{output}"
  end
end
于 2012-05-24T07:45:41.230 回答
-2

将变量传递给系统调用的示例:

irb(main):019:0> b = "test string string string"
=> "test string string string"
irb(main):020:0> system("echo " + "#{b}" + "|" + "awk '{print $2}'")
string
=> true

@Kerrick 如果您有未终止的引号、括号等,您仍然会遇到很多语法错误

也许:

some_var = "'Hello, Im a \"fancy\" variable | with a pipe, double- and single-quotes (terminated and unterminated), and more.'"
    => "'Hello, Im a \"fancy\" variable | with a pipe, double- and single-quotes (terminated and unterminated), and more.'"

irb(main):020:0> system("echo " + "#{some_var}" + "|" + "awk '{print $2}'")Im
        => true
于 2012-05-24T07:21:15.297 回答