views:

200

answers:

2

Calling regex gurus. I'm having some trouble right now with escaping a string in Ruby so that I can pass it into a command line utility using exec, %x{} or similar. The command line command is the TextMate dialog feature, which basically works like this (Run this as a shell script in TextMate.):

$DIALOG -mp "items=('string1','string2', 'string3');" RequestItem

but it can also use a nib file you specify like "path/to/my/nib/file.nib" So, I need to pass that whole command as a string to exec

command = <<string
$DIALOG -mp "items=('string1','string2', 'string3');" "path/to/my/nib/file.nib"
string
exec command

This works fine naturally. The problem that I am running into is that the components of the items array are determined programmatically, so I need to programmatically escape this string in a way that will pass it all to the $DIALOG command properly.

So far, I have determined a need to escape single quotes, double quotes, and newline and tab characters. I've tried a ton of potential regular expression solutions but haven't yet been able to land on a reliable escaping mechanism. Basically, I need to fill in

class String
    def escape_for_dialog
        self
    end
end

with the right self.gsub calls that will escape the strings that I am putting into the parameters. So, let's assume my params are looked up at runtime, here's what I think I need to do using the same example above:

command = <<string
$DIALOG -mp "items=('#{item1.escape_for_dialog}', '#{item2.escape_for_dialog}', '#{item3.escape_for_dialog}');" "path/to/my/nib/file.nib"
string
exec command

I have figured out that the heredoc style helps with not having to remember to escape all the quotes, but the parameters are still problematic so I'm asking for someone better with string manipulation and regular expressions than I am to lend a hand at filling in that string method. I'll be most grateful! :)

A: 

String.inspect will escape delimiters & etc. in a way that makes shell happy:

itemlist = "(#{items.join(', ')})"
command = [
  $DIALOG,
  '-mp',
  itemlist.inspect,
  'path/to/my/nib/file.nib',
].join(' ')
system(command)
Wayne Conrad
A: 

You can use the "escape" library to do shell escaping, or alternatively use exec and pass arrays to it - if done so, exec will auto-escape using the SafeStringValue() macro

Julik