#---Strings---
Any developer worth his salt should be able to wrangle strings to his needs.
Ruby provides so much string methods that you can walk around with a smirk like an old-western gunslinger who just put on his fully-loaded gun belt.
There are many ways to create strings.
You can use either single or double quotes to create strings. But use double quotes if you need to interpolate any ruby code:
x = 42
puts 'answer is #{x}' # => answer is #{x}
puts "answer is #{x}" # => answer is 42
If you hate escaping special characters, use
%Q{}
or %q{}
:
x = "Joe"
puts "Hi \"#{x}\"" # => Hi "Joe"
puts %q{Hi "#{x}"} # => Hi "#{x}"
puts %Q{Hi "#{x}"} # => Hi "Joe"
You can also use something else with
%Q
instead of {}
:
puts %Q[Hi "#{x}"] # => Hi "Joe"
But please, stick to one as much as you can.
Use the weirdo ‘HEREDOCS’ if you want big, multi-line strings:
str = <<~BIGHAIRYSTRING
Meh.
This squiggly heredoc respects
the margin spaces and newlines.
BIGHAIRYSTRING
puts str
## => Meh.
## => This squiggly heredoc respects
## => the margin spaces and newlines.
Find length of string using size
or length
. Both
are same:
p "Boom 💥".size # => 6
p "Boom 💥".length # => 6
You can change a string’s case using upcase
,
downcase
, capitalize
.
p 'hi ruby'.upcase # => "HI RUBY"
p 'HI ruby'.downcase # => "hi ruby"
p 'HI ruby'.swapcase # => "hi RUBY"
p 'hi ruby'.capitalize # => "Hi ruby"
Reverse a string with reverse
:
p 'esac'.reverse # => "case
The above methods don’t change the original string. They just return a new, modified string. But you can use the bang counterpart methods to change the original string itself.
x = 'hi ruby'
x.upcase!
p x # => "HI RUBY"
You can repeat a string ‘n’ times with the *
method
which looks cool:
p 'awesome possum ' * 2
## => "awesome possum awesome possum "
Is the string empty?
p ''.empty? # => true
x = 'encyclopedia'
p x.empty? # => false
Does it include this substring?
p x.include?('cyclop') # => true
Does it start with or end with this substring?
p x.start_with?('en') # => true
p x.end_with?('meh') # => false
Find the index of the substring:
p x.index('cyclop') # => 2
Find the index of the substring from the right-side:
p 'slop slop'.index('slop') # => 0
p 'slop slop'.rindex('slop') # => 5
Now the opposite. Given an index or a range of indices, return the matching substring, aka ‘slicing’:
x = 'kaboom!'
p x[2] # => "b"
p x[2..4] # => "boo" (includes item at the ending index)
p x[2...4] # => "bo" (excludes it)
p x[2..-1] # => "boom!" (-1 means last item's index)
Add 2 or more strings and return a new one:
a, b, c = 'Hello ', 'World', '!'
d = a + b + c
p d # => "Hello World!'
p a, b, c # (a b, c are not affected)
## => ["Hello World!", "World", "!"]
To add one or more strings to an existing string, use
the concat
method:
d = a.concat(b, c)
p d # => "Hello World!"
p a, b, c # (a has changed)
## => ["Hello World!", "World", "!"]
The shovel operator method <<
does the same, but one
string at a time:
a, b, c = 'Hello ', 'World', '!'
d = a << b
p d # => "Hello World"
p a # => "Hello World" (a has changed)
To shovel multiple strings, do this: a << b << c
.
Replace the first occurrence of a string:
p 'The Good The Bad The Ugly'.sub('The', 'THE')
## => "THE Good The Bad The Ugly"
Replace all occurrences:
p 'The Good The Bad The Ugly'.gsub('The', 'THE')
## => "THE Good THE Bad THE Ugly"
You can also use a regex pattern with sub
and gsub
:
p 'Good The Bad The'.gsub(/(\w+) (\w+)/, '\2 \1.')
## => "The Good. The Bad."
Trim whitespaces with the strip
methods:
p " spacious\t".strip # => "spacious"
p " spacious\t".rstrip # => " spacious"
p " spacious\t".lstrip # => "spacious\t"
Remove trailing newlines with chomp
. Useful when
getting input from command line:
p "with newline\n".chomp # => "with newline"
You can insert a text into a string with insert
:
p 'Feb 2025'.insert(3, 'ruary')
## => "February 2025"
You can also delete text within a string with delete
:
p 'February 2025'.delete!('ruary') # => "Feb 2025"
Split based on a character, a substring or a pattern
with split
:
p 'this is a sentence'.split
## => ["this", "is", "a", "sentence"]
p 'col1,col2,col3'.split(',')
## => ["col1", "col2", "col3"]
Join an array of strings using a joining character with
join
:
p ['col1', 'col2', 'col3'].join(' | ')
## => "col1 | col2 | col3"
From the way we’re manhandling the strings above, you probably realized by now that in Ruby they’re mutable.
But it’s nice to have immutable strings sometimes. Like
when you have to be sure that the value you defined
at the start of a program isn’t changed somewhere else
down the line. Use freeze
to make the string
immutable.
secret_passphrase = 'this is such a secret'.freeze
## Somebody trying to change it!
secret_passphrase << 'changing suffix!' rescue nil
## => 💥 blows up with FrozenError without `rescue nil`.
Maybe you could check first if it is frozen?
before
trying to modify it:
p secret_passphrase.frozen? # => true
But I lied. You can still ‘mutate’ it by simply re-assigning a new string to the same variable(?!):
secret_passphrase = "muhaha"
So a better way is to assign these strings to
Ruby constants.
They too can be re-assigned(!?), but you’ll
at least get 2 warnings:
SECRET_PHRASE = 'real secret'.freeze
SECRET_PHRASE = 'changing'
## => warning: already initialized constant SECRET_PHRASE
## => warning: previous definition of SECRET_PHRASE was
## => here
(Ruby constants are just variables beginning with a capital letter, and defined outside a method or a function, with an intention by the programmer to not have its value changed after it is first defined.)
(Also, freeze
is a method on the top-level Object
class. So you can freeze anything in Ruby.)
Strings are just group of characters. A single
character is still an object of the String
class.
p 'a'.class # => String
Use chars
to get an array of characters from a string:
p 'neon'.chars # => ["n", "e", "o", "n"]
You can add longevity to your fingers by typing one character less when you define a character using the questionable quote:
p 'a' # => "a" (u typed 3 keys)
p ?a # => "a" (u only typed 2 now!)
By default ruby strings are UTF-8 encoded.
str = 'whoami'
p str.encoding.name # => "UTF-8"
You can change the encoding of all strings in a file by
adding this comment as the first line in the file:
# encoding: ASCII
.
But if you only want to change a specific string’s
encoding, then use the encode
method:
str = str.encode('US-ASCII')
p str.encoding.name # => "US-ASCII"
If you want to do C-style “sprintf” string formatting,
you can do it with the elegant %
operator method:
base_page_title = 'RubyExamples | %s and %d'
about_page = base_page_title % ['about', 4]
p about_page # => "RubyExamples | about and 4"
You can also use a hash for named substitutions:
base_page_title = 'RubyExamples | %{name} and %{num}'
contact_page = base_page_title % {name: 'contact', num: 5}
p contact_page # => "RubyExamples | contact and 5"
Lots of formatting options are available. See here.
Ruby strings have great regex support with their
match?
, match
and =~
methods that behave exactly
like their Regexp
counterparts.
p 'Vehicle number: AP34BX3439'.match?(/[A-Z]{2}\d{4}$/)
## => true
p 'silly' if 'silly' =~ /y$/ # => "silly"
String#unpack
and its friend Array#pack
are
used for low-level string manipulation. Read this detailed guide.