How to pass a variable to a call to system () in ruby?

Say I have a bunch of text in a variable some_varthat can be almost anything.

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

Also say that in a Ruby CLI application, I want to allow the user to pass this text to any Unix command. I let them enter something like some_var | espeak -a 200 -v en-uswhere the command to the right of the channel is any CLI Unix tool installed on their system.

Let's also say that I have already taken care to separate the choice of variables and the pipe from their input, so I know that I know for 100% exactly which command is after the pipe. (In this case, I want to pass the contents of the variable to espeak -a 200 -v en-us.)

How should I do it? I don’t think I can use the backtick method or literal %x[]. I tried to do the following ...

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

... but any special characters click on things and I cannot delete special characters. What should I do?

+3
source share
5 answers

Oh, happy injection. You are looking for 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"
+4
source

In addition, popenyou can also see Shellwords.escape:

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

This will take care of quoting special characters for you (bash compatible):

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

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

+7
source

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 
+2

! . , 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
0

:

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
-1
source

All Articles