In this post we're going to be talking about escaping characters in Ruby. We'll learn how to escape characters, how it works, and how to avoid escaping altogether for some use cases. If you think you know all about the \
, make sure to read it all and be surprised...
Let's dive right in with character escaping in strings.
Escaping quotes
When using strings in Ruby, we sometimes need to put the quote we used to define the string inside the string itself.
When we do, we can escape the quote character with a backslash \
symbol.
1# Escape quotes in double quoted strings
2"Hello \"world\"!"
3=> "Hello \"world\"!"
4
5# Escape quotes in single quoted strings
6'Hello \'world\'!'
7=> "Hello 'world'!"
Here we can see that Ruby defaults to double quoted strings for output and only escapes those double quotes in the output.
Escape sequences
Besides quotes, there are more symbols we can escape in strings. For example, a newline is represented by \n
. This is called an "escape sequence".
1"Hello\nworld"
2=> "Hello\nworld"
What gets returned is the same string as we created, but as you can see the \n
is highlighted, indicating it's an escape sequence. If we would now print this string we see that the literal \n
is not printed, but an actual newline is printed instead.
1puts "Hello\nworld"
2=> Hello
3world
This doesn't work in single quoted strings. The \n
sequence is interpreted as a literal \n
. In double quoted strings you would have to escape the backslash symbol to accomplish the same result.
1'\n'
2=> "\\n"
Examples of other escape sequences that work the same way are: \t
, \s
and \b
, which represent a tab, a space and a backspace respectively.
Single quotes vs and double quotes
The difference between single and double quoted strings in Ruby is the way the string definitions represent escape sequences.
- In double quoted strings, you can write escape sequences and Ruby will output their translated meaning. A
\n
becomes a newline. - In single quoted strings however, escape sequences are escaped and return their literal definition. A
\n
remains a\n
.
Both string types have their use cases of course. It's likely you'll use double quoted strings with escape sequences to use their translated meaning, a newline or a tab.
Single quotes are useful for avoiding escaping escape sequences themselves. Useful for demonstrating their usage or avoiding accidentally using escape sequences you didn't intent to.
1puts "Line 1\nLine 2"
2=> Line 1
3Line 2
4
5puts 'Using a \n we can indicate a newline.'
6=> Using a \n we can indicate a newline.
Escaping interpolation
Ruby supports interpolation inside strings. But once again, not all string definitions are created equal. Interpolation only works in double quoted strings.
In the code example below we see that interpolation works in a double quoted string, but that Ruby escapes the interpolation sequence in a single quoted string, rendering it useless.
1name = "world"
2
3"Hello #{name}"
4=> "Hello world"
5
6'Hello #{name}'
7=> "Hello \#{name}"
This behavior applies to almost every kind of string "magic". Double quotes support it, single quotes don't.
Percent notation for String
The percent notation in Ruby is something inspired by the Perl programming language and gives us many shorthands for some common type definitions.
The same behavior for single and double quoted strings applies to the percent notation as well.
%()
and%Q()
behave the same way as a double quoted string.%q()
behaves the same way as a single quoted string.
The problem with the percent notation is that you now need to escape the parenthesis characters ()
instead of the quotes when the parenthesis aren't balanced.
Which is why Ruby allows you to use other symbols for the percent notation as well: %[foo]
, %{foo}
, %-foo-
, %?foo?
, etc. It even supports %"foo"
and %'foo'
.
Here we see that Ruby escapes the string for us when using the percent notation.
1%(Hello "world"!)
2=> "Hello \"world\""
3
4# With unbalanced parenthesis
5%(Hello world\)!)
6=> "Hello world)!"
7
8# With balanced parenthesis
9%(Hello (world)!)
10=> "Hello (world)!"
Again, the same rules apply here as with normal single and double quoted strings. Escape sequences and interpolation are escaped by default in single quoted strings.
1name = "world"
2
3%(Hello\n "#{name}"!)
4=> "Hello\n \"world\"!"
5
6%q(Hello\n "#{name}"!)
7=> "Hello\\n \"\#{name}\"!"
8
9%Q(Hello\n "#{name}"!)
10=> "Hello\n \"world\"!"
Escaping characters in regular expressions
Escaping characters also works in regular expressions. In regular expressions many characters represent more than just their literal definition.
The .
is a wild card for any character, brackets []
represent a range or a selection, parenthesis ()
match an expression, etc. To use their literal definitions we can also escape them with the backslash symbol.
1/Hello \[world\]/
2=> /Hello \[world\]/
3
4/\[world\]/ =~ "Hello [world]"
5=> 6
If we didn't escape the brackets, it would instead look for any of the characters between the brackets and find the first match in the character l
in "Hello" on position 3.
1/[world]/ =~ "Hello [world]"
2=> 2 # zero index
To avoid having to escape the forward slash symbol /
, used to define the regular expression, we can use another percent notation.
1%r{/world/}
2=> /\/world\//
Using %r{}
we can define a regular expression where we don't have to escape the forward slash. In the result we can see that Ruby escapes the forward slash for us.
Escaping line breaks
Previously we escaped the "newline" escape sequence \n
in a string in Ruby. Did you know you can also escape a line break in Ruby itself?
For example, we have a very long line for a method call and this breaks our code style guide's max line length.
1ruby_method_with_many_arguments "Hello world", split: " ", join: "\n"
We can place the arguments on separate lines to make each individual line shorter. This works as long as the previous line ends with a comma ,
, operators like the plus symbol +
, or is part of a method call wrapped in parenthesis ()
.
1ruby_method_with_many_arguments "Hello world",
2 split: " ",
3 join: "\n"
4
5ruby_method_with_many_arguments(
6 "Hello world",
7 split: " ",
8 join: "\n"
9)
If instead we'd want to align all arguments on the same indentation level without wrapping it in parenthesis ()
we can use a backslash \
to escape the line break.
1ruby_method_with_many_arguments \
2 my_string,
3 split: " ",
4 join: "\n"
What we do here is not really telling Ruby to escape the newline, but that the statement will continue on the next line.
Escaping line breaks in string definitions
Escaping the line ending also works for things like string definitions. Normally if we have a multi-line string we can use the plus symbol +
to combine the strings on the two lines.
1"foo" +
2 "bar"
3=> "foobar"
This creates two strings on two lines and then combines as one. So it really creates three string objects.
Instead of using a plus symbol, we can escape the line break with a backslash again.
1"foo" \
2 "bar"
3=> "foobar"
The result is the same, or is it?
In the first example we're actually combining two new strings, while in the second example Ruby will only create one. The Ruby interpreter will see the backslash \
as a continuation of the string definition and only create one string based on the two lines. So it's even better for your app's memory usage.
Conclusion
Escaping characters in Ruby, and many other programming languages, can be quite confusing. Suddenly certain combinations of characters get a different meaning inside a double quoted string compared to being used inside a single quoted string.
Hopefully this little guide has helped you with understanding how to properly escape characters and sequences in Ruby. The difference between a double and single quoted string is key here.
The string "magic" of escape sequences and interpolation only really works in double quoted strings, but not in single quoted strings.
There are also other ways of escaping code in Ruby itself. The percent notation helps us with avoiding to escape certain characters all the time, in strings and regular expressions.
But the backslash is also very useful for writing multi-line strings and continuing a line of Ruby code on the next line. Something I use a lot to keep my code clean and readable.
Let us know at @AppSignal if you want to know more, or have a specific question about escaping characters in Ruby.
Fun side-note: for this post, which is written in Markdown, I had to use the backslash symbol quite a lot. Just like in Ruby, Markdown allows escaping of certain characters. Normally in Markdown you can't really wrap a backslash in a code block as it escapes the code block itself. Instead I had it escape a space instead.
1`\` # Doesn't work
2`\ ` # Works :)