Mark Needham

Thoughts on Software Development

Capistrano, sed, escaping forward slashes and ‘p’ is not ‘puts’!

with 2 comments

Priyank and I have been working on automating part of our deployment process and one task we needed to do as part of this is replace some variables used in one of our shell scripts.

All the variables in the script refer to production specific locations but we needed to change a couple of them in order to run the script in our QA environment.

We’re therefore written a sed command, which we call from Capistrano, to allow us to do this.

The Capistrano script looks a little like this:

task :replace_in_shell do
	directory = "/my/directory/path"
	sed_command = "sed 's/^some_key.*$/#{directory}/' shell_script.sh > shell_script_with_qa_variables.sh"
	run sed_command
end

Unfortunately this creates the following sed command which isn’t actually valid syntactically:

sed 's/^some_key.*$//my/directory/path/' shell_script.sh > shell_script_with_qa_variables.sh

We decided to use ‘gsub’ to escape all the forward slashes in the directory path and to work out which parameters we needed to pass to ‘gsub’ we started using irb.

Executing gsub with the appropriate parameters leads us to believe that 2 backslashes will be added:

ruby-1.8.7-p299 > "/my/directory/path".gsub("/", "\\/")
 => "\\/my\\/directory\\/path"

This is because there IRB is implicitly called ‘inspect’ on the result which shows a different string than what we would actually get.

While writing this blog post I’ve also learnt (thanks to Ashwin) that ‘p’ is not the same as ‘puts’ which is what I originally thought and has been driving me crazy as I try to understand why everything I print includes an extra backslash!

The following code:

p "/mark/dir/".gsub("/", "\\/")

is the same as typing:

puts "/mark/dir/".gsub("/", "\\/").inspect

We were able to change our Capistrano script to escape forward slashes like so:

task :replace_in_shell do
	directory = "/my/directory/path"
	sed_command = "sed 's/^some_key.*$/#{directory.gsub("/", "\\/"}/' shell_script.sh > shell_script_with_qa_variables.sh"
	run sed_command
end
Be Sociable, Share!

Written by Mark Needham

November 18th, 2010 at 6:40 pm

Posted in Ruby

Tagged with , ,

  • Sam Sharpe

    err… you could have just used any other character as your sed delimiter… it doesn’t have to be slashes. e.g. `sed ‘s:^some_key.*$:/my/directory/path:’`

  • @976f3b3030c04d45679ca5c6557e3fe7:disqus oh fair point, didn’t realise you could do that! That would have saved 2010 me some pain!