Passing single backslash character as commang line argument

Hi,

I am trying to pass a string as a command line argument to another ruby
program and I am not able to send a single backslash character as part
of that string.

Example:
test1.rb:
test2AbsolutePath = “C:\test2.rb”
text = “Sample Ruby ‘\’ String”
system(“ruby #{test2AbsolutePath} “#{text}””)

test2.rb:
text = ARGV[0]
puts “text: #{text}”

Output :
C:>ruby test1.rb
text: Sample Ruby ‘’ String

Please let me know how to get the backslash character in the string in
the test2.rb program.

Thanks,
Kashyap

Kashyap I. wrote:0

Please let me know how to get the backslash character in the string in
the test2.rb program.

That depends.

If you insist on invoking system with a single string argument, it gets
passed to the shell to execute - something like /bin/sh -c “the string”.

This means the shell breaks it into words, and you have to deal with the
shell’s rules for handling quoting and backslashes:

irb(main):004:0> str = “\” # one backslash
=> “\”
irb(main):005:0> system(“echo “#{str}””)
sh: Syntax error: Unterminated quoted string
=> false
irb(main):006:0> str = “\\” # two backslahses
=> “\\”
irb(main):007:0> system(“echo “#{str}””)

=> true

If instead you use the multi-argument form of system, then you don’t get
a shell - Ruby invokes the program directly with the arguments given.
This means you don’t need to worry about backslashes, or even quoting.

That is:

system("/usr/bin/ruby", test2AbsolutePath, text)

will pass those three args, and you don’t need to quote the text even if
it contains spaces, backslashes or whatever. I strongly recommend you go
this way.

To find the full path to the ruby interpreter, have a look at the
rbconfig library.

Brian C. wrote:

Kashyap I. wrote:0

Please let me know how to get the backslash character in the string in
the test2.rb program.

That depends.

If you insist on invoking system with a single string argument, it gets
passed to the shell to execute - something like /bin/sh -c “the string”.

This means the shell breaks it into words, and you have to deal with the
shell’s rules for handling quoting and backslashes:

irb(main):004:0> str = “\” # one backslash
=> “\”
irb(main):005:0> system(“echo “#{str}””)
sh: Syntax error: Unterminated quoted string
=> false
irb(main):006:0> str = “\\” # two backslahses
=> “\\”
irb(main):007:0> system(“echo “#{str}””)

=> true

If instead you use the multi-argument form of system, then you don’t get
a shell - Ruby invokes the program directly with the arguments given.
This means you don’t need to worry about backslashes, or even quoting.

That is:

system("/usr/bin/ruby", test2AbsolutePath, text)

will pass those three args, and you don’t need to quote the text even if
it contains spaces, backslashes or whatever. I strongly recommend you go
this way.

To find the full path to the ruby interpreter, have a look at the
rbconfig library.

Brian,
I changed the code as you suggested, but I still do not get see the
single backslash appearing in the string that gets sent to the test2.rb

Here’s the code:
test1.rb:
test2AbsolutePath = “C:\test2.rb”
text = “Sample Ruby ‘\’ String”
system(“ruby”, test2AbsolutePath, text)

test2.rb:
text = ARGV[0]
puts “text: #{text}”

Current Output:
text: Sample Ruby ‘’ String

Expected Output:
text: Sample Ruby ‘’ String

Please let me know what needs to be modified to get the single backslash
in the output.

On 9/28/2010 1:04 AM, Brian C. wrote:

Kashyap I. wrote:

I changed the code as you suggested, but I still do not get see the
single backslash appearing in the string that gets sent to the test2.rb

When I run it under Linux, I get:

text: Sample Ruby ‘’ String

Windows is broken in so many ways, I can only guess this is one of them.

I took a swing at this under Windows using both the native build of Ruby
and the Cygwin build, and this looks like a bug in the system method
under the Windows build that crops up when the backslash immediately
precedes a single quote. I set the text variable in test1.rb to the
following:

text = “Sample Ruby \ \ “\” ‘\’ String”

When run using the Windows Ruby build, I get:

text: Sample Ruby \ ** “” ‘’ String

However, when I run it with the Cygwin build of Ruby, I get what we
expect to see:

text: Sample Ruby \ ** “” ‘’ String

Cygwin itself is most likely handling this for Ruby in that environment,
but since Cygwin relies on Windows to spawn processes under the covers,
it must also have some trick to handle this case. That trick should be
able to be implemented in the Windows build of Ruby.

Please let me know what needs to be modified to get the single backslash
in the output.

I don’t use Windows. You could try doubling the backslash:

text.gsub!(/\/, ‘\\\\’)

Unfortunately, doubling the backslashes doesn’t work around this issue:

text = “Sample Ruby \ \ “\” ‘\\’ String”

Yields:

text: Sample Ruby \ ** “” ‘\’ String

Which is what we would expect to see when using a run of 4 backslashes
like that. Windows is definitely messed up, but Cygwin proves that
there is a way to deal with that at least in this case.

-Jeremy

Kashyap I. wrote:

I changed the code as you suggested, but I still do not get see the
single backslash appearing in the string that gets sent to the test2.rb

When I run it under Linux, I get:

text: Sample Ruby ‘’ String

Windows is broken in so many ways, I can only guess this is one of them.

Please let me know what needs to be modified to get the single backslash
in the output.

I don’t use Windows. You could try doubling the backslash:

text.gsub!(/\/, ‘\\\\’)

On Sep 27, 8:25 pm, Kashyap I. [email protected] wrote:

Please let me know what needs to be modified to get the single backslash
in the output.

One important thing to mention is that multiple arguments with
Kernel.system are broken in 1.8.x. Patches are applied to 1.9.x to
solve that issue.

A workaround under 1.8 is use Rake and the alt_system:

http://github.com/jimweirich/rake/blob/master/lib/rake/alt_system.rb

On Sep 27, 2:40 pm, Kashyap I. [email protected] wrote:

system(“ruby #{test2AbsolutePath} "#{text}"”)
the test2.rb program.

Please include which version of Ruby are you using.

Ruby 1.8.x versus 1.9.1, specially 1.9.2, differ in how commands are
processed by Kernel.system

Also, pretty much all the modern tools and command line applications
can parse file paths with backslashes as normally as forward slashes.

If what are you trying to achieve is feed backslashes into evaluate
(ruby -e) then you need to use double quotes and escape inner double
quotes inside:

ruby -ve “puts "hello"”