Ker*_*ick 3 ruby unix command-line command-line-interface
假设我在变量中有一堆文本some_var,这几乎可以是任何东西.
some_var = "Hello, I'm a \"fancy\" variable | with a pipe, double- and single-quotes (terminated and unterminated), and more."
Run Code Online (Sandbox Code Playgroud)
我们还要说,在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")
Run Code Online (Sandbox Code Playgroud)
...但是任何特殊字符搞砸了,我无法删除特殊字符.我该怎么办?
除此之外popen你还可以看看Shellwords.escape:
puts Shellwords.escape("I'm quoting many different \"''' quotes")
=> I\'m\ quoting\ many\ different\ \"\'\'\'\ quotes
Run Code Online (Sandbox Code Playgroud)
这将负责为您引用特殊字符(兼容bash):
system("echo '#{Shellwords.escape(some_var)}' | ....")
Run Code Online (Sandbox Code Playgroud)
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/shellwords/rdoc/Shellwords.html
哦,开心的注射。您正在寻找
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"
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)