Ruby: escape escape sequence? - ruby

There is a string:
str = "foo\nbar"
How can I escape it to:
'foo\nbar'
?
I noticed "#{str}" doesn't work.

str.inspect Should do it for you

Add another \:
"foo\\nbar" == 'foo\nbar' #=> true
Single-quoted strings do not have interpolation, so #{str} does nothing special in them.

Related

Output string containing escape characters

I have a string:
s = "\t\n"
I intend to output:
\t\n
When I do
puts s
I see nothing. How should I do it?
That's because \n and \t are escape sequences
A single-quoted strings don’t process ASCII escape codes, and they don’t do string interpolation while double-quoted does both.
So if you want that behaviour, you should do
s = '\t\n'
Just use inspect to see the "raw" escape sequences.
s = "\t\n"
puts s.inspect
# >> "\t\n"
p s # >> "\t\n"
or
puts s.inspect[1...-1] # >> \t\n

Ruby - substitute \n if not \\n

I'm trying to do a regex with lookbehind that changes \n to but not if it's a \\n.
My closest attempt has no effect:
text.gsub /(?<!\\)\n/, ''
Unfortunately, no number of backslashes in the lookbehind seem to fix the problem. How can I address this?
You need to double the backslash before the n in the regex, otherwise it's looking for a newline instead of a literal backslash followed by n:
irb(main):001:0> puts "hello\\nthere\\\\n".gsub(/(?<!\\)\\n/, ' ')
hello there\\n
You don't need anything special. "\n" is a single character. It does not include a "\" or "n" character.
text.gsub(/\n/, "")
But instead of that, you should do:
text.gsub("\n", "")
or
text.tr("\n", "")
But I would do:
text.tr($/, "")

Regex to match any character except a backslash

How can i say "all symbols except backslash" in Ruby character class?
/'[^\]*'/.match("'some string \ hello'") => should be nil
Variant with two backslashed doesn't work
/'[^\\]*'/.match("'some string \ hello'") => 'some string \ hello' BUT should be nil
Your problem is not with your regex; you got that right. Your problem is that your test string does not have a backslash in it. It has an escaped space, instead. Try this:
str = "'some string \\ hello'"
puts str #=> 'some string \ hello'
p /'[^\\]*'/.match(str) #=> nil
You need to escape the backslash:
[^\\]*
because backslash is the escape character in regular expressions, thus escaping the closing bracket here.
If you want to verify that the whole string contains non-backslash characters, then you need anchors:
^[^\\]*$
There's actually not a backslash in your string to match against. Try taking a look at just your input:
"'some string \ hello'".length # => 20
"a\ b".length # => 3
The "\ " in double quotes is being escaped into just a space:
irb(main):014:0> " "[0].to_i # => 32
irb(main):015:0> "\ "[0].to_i # => 32
irb(main):016:0> "\ ".size #=> 1
If you want to match no slash, you'll need two, like in your second example, which looks good to me:
/'[^\\]*'/.match("'some string \\ hello'") # => nil
This is relevant to Csharp.. but idk it might help you.
[^\\\\]*
four slashes instead of two.

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

How to add a single backslash character to a string in Ruby?

I want to insert backslash before apostrophe in "children's world" string. Is there a easy way to do it?
irb(main):035:0> s = "children's world"
=> "children's world"
irb(main):036:0> s.gsub('\'', '\\\'')
=> "childrens worlds world"
Answer
You need some extra backslashes:
>> puts "children's world".gsub("'", '\\\\\'')
children\'s world
or slightly more concisely (since you don't need to escape the ' in a double-quoted string):
>> puts "children's world".gsub("'", "\\\\'")
children\'s world
or even more concisely:
>> puts "children's world".gsub("'") { "\\'" }
children\'s world
Explanation
Your '\\\'' generates \' as a string:
>> puts '\\\''
\'
and \' is a special replacement pattern in Ruby. From ruby-doc.org:
you may refer to some special match variables using these combinations ... \' corresponds to $', which contains string after match
So the \' that gsub sees in the second argument is being interpreted as a special pattern (everything in the original string after the match) instead of as a literal \'.
So what you want gsub to see is actually \\', which can be produced by '\\\\\'' or "\\\\'".
Or, if you use the block form of gsub (gsub("xxx") { "yyy" }) then Ruby takes the replacement string "yyy" literally without trying to apply replacement patterns.
Note: If you have to create a replacement string with a lot of \s you could take advantage of the fact that when you use /.../ (or %r{...}) you don't have to double-escape the backslashes:
>> puts "children's world".gsub("'", /\\'/.source)
children\'s world
Or you could use a single-quoted heredoc: (using <<'STR' instead of just <<STR)
>> puts "children's world".gsub("'", <<'STR'.strip)
\\'
STR
children\'s world
>> puts s.gsub("'", "\\\\'")
children\'s world
Your problem is that the string "\'" is meaningful to gsub in a replacement string. In order to make it work the way you want, you have to use the block form.
s.gsub("'") {"\\'"}

Resources