How to gsub slash "/" with back slash and slash "\/" in ruby - ruby

I try to modify "/foo/bar/dir" to "\/foo\/bar\/dir" by ruby gsub command.
I test it in irb the result is
x = "/foo/bar/dir"
x.gsub("/","\/")
=> "/foo/bar/dir"
x.gsub("/","\\/")
=> "\\/foo\\/bar\\/dir"
Is it possible to replace "/" with "/" by gsub ?
Source of problems:
I try to execute "string in command line" and "real_path" is my variable
real_path = "/home/me/www/idata"
path = real_path.gsub("/","\\/")
=> \\/home\\/me\\/www\\/idata
# But what I expect is \/home\/me\/www\/idata
run "sed 's/SHARE_PATH/#{path}/g' #{path}/config/sphinx.yml > #{path}/config/sphinx.tmp.yml"
result from "run" command is
"sh -c 'sed '\''s/SHARE_PATH/\\/home\\/me\\/www\\/idata\\/shared/g .... "
I need is only one back slash like
"sh -c 'sed '\''s/SHARE_PATH/\/home\/me\/www\/idata\/shared/g .... "
"run" is command from Capistrano
my solution is
use single quote instead of double quote like this
path = real_path.gsub("/",'\/')

You have written:
x = "/foo/bar/dir"
x.gsub("/","\\/")
=> "\\/foo\\/bar\\/dir"
so You did what You had asked before. x.gsub("/","\\/") in fact evaluates to "\/foo\/bar\/dir" but irb prints return value of inspect method instead of to_s.
Edit: Did You mean
real_path.gsub("/","\/")
istead of
real_path.gsub("\/","\/")
Anyway the output is correct - You changed / with \/ so You have
"sh -c 'sed '\''s/SHARE_PATH/\/home\/me\/www\/idata\/shared/g'\'' .... "`
instead of
`"sh -c 'sed '\''s/SHARE_PATH//home/me/www/idata/shared/g'\'' .... "`
and result is different from irb's result (notice the lack of doubled backslash).
For path manipulation I recommend using File.join (documentation)
By the way: why are You modifying the path this way? (1)
Edit2: Why are You asking about changing "/" to "/" but write the following line?
path = real_path.gsub("\/","\\/")
What are You trying to achieve? And what is Your answer to question (1) ?
Edit3:
Here We go:
>> real_path = "/foo/bar/dir"
=> "/foo/bar/dir"
>> path = real_path.gsub("/", "\\/")
=> "\\/foo\\/bar\\/dir"
>> puts "sed 's/SHARE_PATH/#{path}/g' #{path}/config/sphinx.yml > #{path}/config/sphinx.tmp.yml"
sed 's/SHARE_PATH/\/foo\/bar\/dir/g' \/foo\/bar\/dir/config/sphinx.yml > \/foo\/bar\/dir/config/sphinx.tmp.yml
=> nil
>>
but I do not understand why You need backslash in a path?

Yes
irb(main):028:0> (t = x.gsub("/", "\\/")) && nil
=> nil
irb(main):029:0> t
=> "\\/foo\\/bar\\/dir"
irb(main):030:0> puts t
\/foo\/bar\/dir
=> nil
Your first example actually did what you wanted, but the .inspect method that irb is using is escaping backslashes, so it looked like there were extras. If you had used puts you would have seen the real result.

Related

Regex on directory for linux

I have tried the regex from the answer of this question: check directory path for symbols range and ".." up directory sign
Which was not working for me. If I passed my script a directory like this "/home/local/NKU/dixonc3/test/" it would not match the regex.
So I just tried to start out with something simple such as if a directory starts with a slash / or a tilde ~ it will pass.
^[~/].*$
even when I use this as my regex in the code below if I pass it a ~ tilde it gives me an error
./rename.rb:23:in `exists?': can't convert nil into String (TypeError)
from ./rename.rb:23:in `rename'
from ./rename.rb:33:in `<main>'
Below is my Ruby code
currDir = ""
#
# regex is from stack overflow question:
#dirRegex = Regexp.new '^(?!.*[\\/]\.{2}[\\/])(?!\.{2}[\\/])[-\w.\\/]+$'
dirRegex = Regexp.new '^[~/]*$'
if ARGV.length == 1 && ($1.to_s.match dirRegex)
currDir = $1
puts $1
puts "#{currDir}"
puts ARGV.length
else
currDir = "./"
puts $1
puts "#{currDir}"
puts ARGV.length
end
Your regex is matching on a single character (~ or / or nothing). It should be:
dirRegex = Regexp.new '^[~/].*$'
To match on an opening character of ~ or / and the rest.

How do I run Unix commands using system and backticks?

This works:
system("ruby #{File.dirname(__FILE__) + '/Test')}")
but this
`ruby #{File.dirname(__FILE__) + '/Test'}`
does not run the script Test
And this:
system("ruby #{File.dirname(__FILE__) + '/Test #{arg}'")
does not take the arg value.
What am I doing wrong?
The second doesn't work because there's a unbalanced trailing double-quote (") and closing parenthesis ()) which is probably raising and error, but you're not seeing it because the back-ticks ignore STDERR:
`ruby #{File.dirname(__FILE__) + '/Test'")}`
The third one doesn't work because you're trying to interpolate a variable into a fixed string enclosed in single-quotes, which is also missing a terminating }:
system("ruby #{File.dirname(__FILE__) + '/Test #{arg}'")
You'd see this stand out if you didn't embed the string calculation in your string interpolation:
cmd_file = File.dirname(__FILE__) + '/Test #{arg}'
system("ruby #{ cmd_file }")
Fixing the quoting and using the intrinsic File.join for correctness:
cmd_file = File.join(File.dirname(__FILE__), "Test #{arg}")
system("ruby #{ cmd_file }")

How to pass ruby variable into sed command in Shell?

This is my code. I want to grab the p's value and insert it into the file changed.txt when matched 1. But it doesn't do what I want to, it seems it doesn't know what #{p} is
Net::SSH.start( "192.168.2.1", "root", :password => "password") do |ssh|
p = ssh.exec! "java -cp /var/lib/sonar/dev-tools.jar au.com.Tool test"
# puts #{p}
ssh.exec! "sed 's/1/#{p}/g' changed.txt"
end
The passing of the p value the way you have it should work fine. However, the sed command doesn't change the file. If you want it to change the file in place, use the -i option like so:
ssh.exec! "sed -i 's/1/#{p}/g' changed.txt"
Or if you want the changes in a different file, then use:
ssh.exec! "sed 's/1/#{p}/g' changed.txt > newfile.txt"
An alternative option would be:
ssh.exec! "sed -i 's/1/" + p + "/g' changed.txt"

How can I use \w in double quoted string in Ruby

I'm using Capistrano for deployment and I need to run a command for setting the correct environment in the .htaccess file on the server.
I do that with sed like this: run "sed -i -r 's/APPLICATION_ENV \w+/APPLICATION_ENV #{stage}/' #{current_release}/public/.htaccess"
My problem is that the \w+ is escaped by Ruby/Cap and the regexp ends up trying to match only w+. If I use \\w+ I end up with a regexp that attempts to match \\w+.
How can I have an interpolated double quoted string and successfully escape the \w? Do I really need to change to concatenation of single quoted string and variables?
On my sysem your sample works but you could try it with one of these two (comment the ones out you don't use)
begin
stage = "stage"
current_release = "current_release"
s = "sed -i -r 's/APPLICATION_ENV \\w+/APPLICATION_ENV #{stage}/' #{current_release}/public/.htaccess"
s = "sed -i -r 's/APPLICATION_ENV #{"\\w+"}/APPLICATION_ENV #{stage}/' #{current_release}/public/.htaccess"
s = "sed -i -r 's/APPLICATION_ENV #{92.chr}w+/APPLICATION_ENV #{stage}/' #{current_release}/public/.htaccess"
puts s
system s
rescue
puts $!
system('pause')
end

Using Named Captures with regex match in Ruby's case...when?

I want to parse user input using named captures for readability.
When they type a command I want to capture some params and pass them. I'm using RegExps in a case statement and thus I can't assign the return of /pattern/.named_captures.
Here is what I would like to be able to do (for example):
while command != "quit"
print "Command: "
command = gets.chomp
case command
when /load (?<filename>\w+)/
load(filename)
end
end
named captures set local variables when this syntax.
regex-literal =~ string
Dosen't set in other syntax. # See rdoc(re.c)
regex-variable =~ string
string =~ regex
regex.match(string)
case string
when regex
else
end
I like named captures too, but I don't like this behavior.
Now, we have to use $~ in case syntax.
case string
when /(?<name>.)/
$~[:name]
else
end
This is ugly but works for me in Ruby 1.9.3:
while command != "quit"
print "Command: "
command = gets.chomp
case command
when /load (?<filename>\w+)/
load($~[:filename])
end
end
Alternatively you can use the English extension of $~, $LAST_MATCH_INFO.

Resources