Ruby string escape characters - ruby

I want to get the quoted string in the line below into a string exactly as-is, but I am tripping on the necessary escape sequences for Ruby. mycommand.cmd is really a wrapper for powershell.exe so I want to preserve everything between the quotes, and hold onto the escape characters that are already there.
mycommand.cmd "^|foreach-object { \"{0}=={1}\" -f $_.Name, $_.Found }"

Use single quotes :
ruby-1.9.3-p0 :001 > '^|foreach-object { \"{0}=={1}\" -f $.Name, $.Found }'
=> "^|foreach-object { \\\"{0}=={1}\\\" -f $.Name, $.Found }"
The only escape characters in single quotes are : \' and \\

Related

Replacing ' by \' in Ruby [duplicate]

s = "#main= 'quotes'
s.gsub "'", "\\'" # => "#main= quotes'quotes"
This seems to be wrong, I expect to get "#main= \\'quotes\\'"
when I don't use escape char, then it works as expected.
s.gsub "'", "*" # => "#main= *quotes*"
So there must be something to do with escaping.
Using ruby 1.9.2p290
I need to replace single quotes with back-slash and a quote.
Even more inconsistencies:
"\\'".length # => 2
"\\*".length # => 2
# As expected
"'".gsub("'", "\\*").length # => 2
"'a'".gsub("'", "\\*") # => "\\*a\\*" (length==5)
# WTF next:
"'".gsub("'", "\\'").length # => 0
# Doubling the content?
"'a'".gsub("'", "\\'") # => "a'a" (length==3)
What is going on here?
You're getting tripped up by the specialness of \' inside a regular expression replacement string:
\0, \1, \2, ... \9, \&, \`, \', \+
Substitutes the value matched by the nth grouped subexpression, or by the entire match, pre- or postmatch, or the highest group.
So when you say "\\'", the double \\ becomes just a single backslash and the result is \' but that means "The string to the right of the last successful match." If you want to replace single quotes with escaped single quotes, you need to escape more to get past the specialness of \':
s.gsub("'", "\\\\'")
Or avoid the toothpicks and use the block form:
s.gsub("'") { |m| '\\' + m }
You would run into similar issues if you were trying to escape backticks, a plus sign, or even a single digit.
The overall lesson here is to prefer the block form of gsub for anything but the most trivial of substitutions.
s = "#main = 'quotes'
s.gsub "'", "\\\\'"
Since \it's \\equivalent if you want to get a double backslash you have to put four of ones.
You need to escape the \ as well:
s.gsub "'", "\\\\'"
Outputs
"#main= \\'quotes\\'"
A good explanation found on an outside forum:
The key point to understand IMHO is that a backslash is special in
replacement strings. So, whenever one wants to have a literal
backslash in a replacement string one needs to escape it and hence
have [two] backslashes. Coincidentally a backslash is also special in a
string (even in a single quoted string). So you need two levels of
escaping, makes 2 * 2 = 4 backslashes on the screen for one literal
replacement backslash.
source

Ruby Filter gsub replace \\n

I want to replace '\\n' with '\n'
i am using the gsub method but cannot replace
ruby
{
code => "#mystring=event.get('stockLines');
#mystring=#mystring.gsub('\\\n', '\n');"
}
You need to use "\n" not '\n' in your gsub. The different quote marks behave differently.
Read more
In your case:
#mystring.gsub("\\n", "\n")
The essential difference between the two literal forms of strings (single or double quotes) is that double quotes allow for escape sequences while single quotes do not!
Escaping of the backslash can be a bit weird.
For a regular Ruby script the code would be:
#mystring = event.get('stockLines').gsub('\\\\\n', '\n')
It seems like in logstash config the code is also in a string, so it needs to be escaped once more, i.e.:
ruby
{
code => "#mystring = event.get('stockLines').gsub('\\\\\\\\\\n', '\\n');"
}

How to print \" in Ruby

In ruby, quotation marks can be printed in a string if it is immediately preceded with a backslash: print " \" ".
But how do i print \" in ruby without the backslash disappearing due to the presence of the quotation mark immediately before it?
Thanks in advance.
You can use single quote (') instead of double quote (") to prevent interpretation of escape sequence:
irb(main):001:0> print '\"'
\"=> nil
or %q{...} in case there are many 's in the string:
irb(main):002:0> print %q{\"}
\"=> nil

Single quotes vs double quotes

I am trying to split a string by three consecutive newlines ("\n\n\n"). I was trying str.split('\n\n\n') and it didn't work, but when I changed to str.split("\n\n\n"), it started to work. Could anyone explain to me why such behaviour happens?
String in single quotes is a raw string. So '\n\n\n' is three backslashes and three n, not three line feeds as you expected. Only double quotes string can be escaped correctly.
puts 'abc\nabc' # => abc\nabc
puts "abc\nabc" # => abc
# abc
Single quoted string have the actual/literal contents, e.g.
1.9.3-p194 :003 > puts 'Hi\nThere'
Hi\nThere
=> nil
Whereas double-quoted string 'interpolate' the special characters (\n) and do the line feed, e.g.
1.9.3-p194 :004 > puts "Hi\nThere"
Hi
There
=> nil
1.9.3-p194 :005 >
Best practice Recommendations:
Choose single quotes over double quotes when possible (use double quotes as needed for interpolation).
When nesting 'Quotes inside "quotes" somewhere' put the double ones inside the single quotes
In single-quoted string literals, backslashes need not be doubled
'\n' == '\\n'

Ruby gsub doesn't escape single-quotes

I don't understand what is going on here. How should I feed gsub to get the string "Yaho\'o"?
>> "Yaho'o".gsub("Y", "\\Y")
=> "\\Yaho'o"
>> "Yaho'o".gsub("'", "\\'")
=> "Yahooo"
\' means $' which is everything after the match.
Escape the \ again and it works
"Yaho'o".gsub("'", "\\\\'")
"Yaho'o".gsub("'", "\\\\'")
Because you're escaping the escape character as well as escaping the single quote.
This will also do it, and it's a bit more readable:
def escape_single_quotes(str)
str.gsub(/'/) { |x| "\\#{x}" }
end
If you want to escape both a single-quote and a backslash, so that you can embed that string in a double-quoted ruby string, then the following will do that for you:
def escape_single_quotes_and_backslash(str)
str.gsub(/\\|'/) { |x| "\\#{x}" }
end

Resources