Strings and Symbols

How to work with text in Ruby and how strings differ from symbols

Scroll down...

Content

Resources

Comments

In this lesson, we'll cover strings and all the interesting things you can do with them in Ruby as well as their less familiar cousins, symbols. The goal is for you to absorb the basic operations you can perform on a string and a sense for how versatile they are. You should also be comfortable working with symbols since you'll see them a lot in Rails.

Strings

Strings are a huge part of web programming and you'll run into them everywhere from variable names to user input to giant gobs of HTML text to handling big dictionary files. They're actually pretty simple at the core but, for being just a jumble of characters, strings have some pretty cool properties in Ruby and you can do a whole lot to manipulate them.

This lesson should give you an appreciation for the ways you can mess with strings and some of the handy methods that Ruby gives you along the way to make your life easier.

Strings are just made up of individual characters and denoted with quotes.

> I confuse Ruby and will throw an error
#=> NameError: uninitialized constant Ruby
> "I do not because I have quotes"
#=> "I do not because I have quotes"

Double Quotes vs Single Quotes

Double Quotes are usually interchangeable with Single Quotes. There's almost no difference and you're free to use either. There are a few good reasons why you might choose one or the other, though, including using quotes within a string or interpolating values.

Alternate Quote Types to Show Quotes Within Strings
> my_long_string = "And she said, 'Cool program!'"
#=> "And she said, 'Cool program!'"

Note that you can accomplish the same type of thing by escaping the quote characters (see below).

String Interpolation

String Interpolation occurs when you want to plug something else into a string, like a variable. You'll find yourself using this a lot, for instance, when you make websites with dynamic text content that needs to change depending on who is logged in.

Simply use the pound symbol and curly braces #{} to do so, and the output of whatever is within those curly braces will be converted to a string and, presto! You've got a new string:

> my_name = "Tiny Tim"
=> "Tiny Tim"
> my_string = "My name is #{my_name}!"
=> "My name is Tiny Tim!"

The key point here, though, is that interpolation only works inside DOUBLE quotes.

Also, keep the interpolated stuff brief or your code won't be very legible.

Single quotes, on the other hand, will escape every special character in the string and treat it like a normal letter (so the pound-curly-braces has no special meaning):

> my_name = "Neo"
=> "Neo"
> my_string = 'My name is #{my_name}!'
=> "My name is \#{my_name}!"  # Hey! That's not what we wanted!

Escaping Characters

Escaping characters just means telling the output program to not treat them specially at all (like the pound symbol in the example above, which has special meaning before the curly braces). You do so by adding a back slash \ before whatever you want to escape.

Sometimes you'll see what looks like a strange jumble of characters in your output, with lots of those '\' floating around, and you'll know that you've got some (perhaps unintentional!) escaping going on behind the scenes.

> now = "RIGHT NOW"
=> "RIGHT NOW"
> puts "interpolating #{now} but not \#{now}"
"interpolating RIGHT NOW but not #{now}"
=> nil            # Remember, puts returns nil!

IRB shows you the backslashes, but they'll be hidden in your puts output.

As you can imagine, this could get pretty tedious if you're trying to output a blog post or some other long batch of text that contains lots of mixed characters and don't want to manually or programmatically replace special characters, so later we'll see some simple convenience methods to use to take care of those issues for you.

Special Characters

There are some special characters that are actually denoted using the backslash and you'll want to know the key ones, which will probably pop up again and again:

  • \n will output a new line
  • \r is a newline too (carriage return)
  • \t will output a tab
> puts "let's put a bunch of newlines between this\n\n\nand this."
let's put a bunch of newlines between this


and this.
#=> nil

The to_s Method

to_s is a method that will try to convert anything into a string:

> 12345.to_s
=> "12345"

This method gets called a LOT behind the scenes later on... basically anytime Ruby or especially Rails is outputting or rendering something (like a variable), it will call to_s on it to make it a nice friendly string first. You can actually override this method if you want to, which we'll play with when we're using Rails.

Concatenation

Combining Strings without using interpolation can be done using "concatenation", or basically just adding them together:

> my_name = "Billy Bob"
> "hello" + " world" + ", say I, the great " + my_name + "!"
#=> "hello world, say I, the great Billy Bob!"

Instead of adding them with a plus +, you can also use the friendly shovel operator << to append to a string (just like with arrays...):

> "howdy " << "fella!"
#=> "howdy fella!"

It's typically better (and more legible) to build your strings using interpolation if you can:

> my_name = "Billy Bob"

# Not preferred...
> "hello" + " world" + ", say I, the great " + my_name + "!"
#=> "hello world, say I, the great Billy Bob!"

# Better
> "hello world, say I, the great #{my_name}!"
#=> "hello world, say I, the great Billy Bob!"

Accessing Specific Characters or Substrings

To Access a Specific Character or Substring of a string, just treat it like an array! A string acts like a zero-indexed array that ends at -1, so use [0] to access the first letter, [-1] to access the last letter, and [n..m] to pluck a substring:

> s = "hello"
#=> "hello"
> s[0]
#=> "h"
> s[-1]
#=> "o"
> s[-2]
#=> "l"
> s[2..4]
#=> "llo"
> s[1..-2]
#=> "ell"

splitting Strings Apart

Break a String into Pieces using split, which creates an array of substrings that are broken up based on whatever character you passed in:

> list = "eggs, milk, cheese and crackers"
#=> "eggs, milk, cheese and crackers"
> list.split(", ")
#=> ["eggs", "milk", "cheese and crackers"]
> list.split(" ")
#=> ["eggs,", "milk,", "cheese", "and", "crackers"]

You can also split based on individual characters by passing either a blank string or a blank regular expression (denoted by //):

> list.split("")      # or also list.split(//)
=> ["e", "g", "g", "s", ",", " ", "m", "i", "l", "k", ",", " ", "c", "h", "e", "e", "s", "e", " ", "a", "n", "d", " ", "c", "r", "a", "c", "k", "e", "r", "s"] 

Getting User Input with gets

When you write your Ruby programs, you'll probably want to ask for User Input... which is easy with gets, which then waits for the user to type something. Think of it as the opposite of puts.

You'll want to store whatever the user types in using a variable and be sure to trim off the extra line break (from when the user hit the enter key) using chomp:

> player1 = gets    
Erik                 # this was typed in manually
#=> "Erik\n"         # woah, let's get rid of that \n
> player1 = gets.chomp
Erik
#=> "Erik"           # better.

Chomping and Stripping Newlines and Spaces

chomp will cut off a space or newline at the END of the string (and can take an optional input so you can specify what exactly to chomp off).

strip will remove ALL spaces and newlines from BOTH the beginning AND end of the string:

> " dude \n".chomp
=> " dude "         # still have the extra spaces
> " dude \n".strip
=> "dude"           # clean as a whistle.

Of course, it's up to you to figure out if your user has entered something illegal or harmful, but at least you have an easy job removing extraneous spaces and returns.

Other Helpful String Methods

  • length to get the length of the string
  • downcase to convert "ALL THIS" to "all this"
  • upcase to convert "all this" back to "ALL THIS"
  • reverse to convert "hello" to "olleh"
> "howdy".length
#=> 5
> "HOWdy".downcase
#=> "howdy"
> "HOWdy".upcase
#=> "HOWDY"
> "howdy".reverse
#=> "ydwoh"
  • ljust will let you pad your string with extra spaces (or any other character you choose) up until a specified total amount of characters. This can be handy for prettying up some of your command line outputs.
  • rjust does the same thing but pushes your string to the right.
  • center is the same idea but it centers your string.
> "hi".ljust(4) 
#=> "hi  "
> "hi".ljust(6,"*") 
#=> "hi****"
> "hi".rjust(6) 
#=> "    hi"
> "hi".center(6,"!") 
#=> "!!hi!!"

Backtics `

Fun fact: Strings made with the backtick characters ` (which is usually located on the same key as the tilde ~) are actually interpolated and run by your operating system, so in IRB if you type > puts `ls` on a mac, it will actually output your directory contents!

You also see the backtics come up a lot in Markdown editing. Markdown is just a shorthand way of writing text files that convert into HTML. You use backtics when you want a code block to show up. This document was written using Markdown!

Simple Searching and Replacing in Strings

What about all the times you may want to search for or replace within strings?

There's a handy method for strings called gsub (as in gsub(pattern, replace_with_this)), which finds any occurrances of that pattern and replaces it with whatever you want:

> "hello".gsub("l","r")
=> "herro"

Regular Expressions

But what if you want to go looking for more advanced patterns than just simple letters? Pretty much anytime you've got a function that needs to go mucking through a string looking for patterns, you can employ a Regular Expression.

Regular Expressions are really just a special syntax that is used to find things (and not just in Ruby, they're used all over the place). It's beyond the scope of this course to explicitly teach them but you can check them out at the following two sites, which together teach and let you play with regex's. You'll find yourself going back to Rubular if you ever actually need to actually use a Regex.

Glance over these two resources, bookmark Rubular, and then move on:

  1. RegexOne
  2. Rubular

Once you know how to match stuff using Regex's, you'll feel ready to take on any big dictionary files or big batches of questionable user input that needs to be standardized. But be careful, it can be too tempting to go hog-wild with your expressions. It's something you should at least know the basics of but probably will not be applying all that often "in the wild".

Symbols

The last thing to cover is Symbols, which start creeping up all over the place when you get into Rails and even Hashes. Symbols are denoted with the colon before the name:

> :i_am_a_symbol
#=> :i_am_a_symbol
> "i_am_a_string"
#=> "i_am_a_string"

A symbol is basically like a string without any depth... string lite, if you will.

A string is Mutable, meaning it can be added to, reversed, and generally messed with in a hundred different ways. Whenever you have text that you want to play around with or use as, well, text, just stick with strings.

But sometimes all you want is a name, like when you're using a hash key. In that case, it makes sense to use symbols. Symbols are immutable, so they don't change. They are also only stored in memory in one place, wherease strings have a new place in memory each time you declare one:

> "hello".object_id
=> 70196107337380
> "hello".object_id
=> 70196107320960       # different
> :hello.object_id
=> 461128
> :hello.object_id
=> 461128               # same!

While you're learning, just stick with strings until you see the examples using symbols, which will mostly be with hash keys.

Code Review

The important bits of code from this lesson

#Single and double quotes are used for Strings
string1 = "hello"
string2 = 'hello'
string1 == string2 #=> true

#Double quotes allow interpolation of variables or code
placeholder = "string interpolation"
"I can use #{placeholder} in double-quoted strings"
#=> "I can use string interpolation in double-quoted strings"
'I cannot use #{placeholder} in single-quotes strings'
#=> => "I cannot use \#{placeholder} in single-quotes strings"

#Combine strings but not with numbers
"hello " + "world"  #=> "hello world"
"hello " + 3 #=> TypeError: can't convert Fixnum into String
"hello " +3.to_s #=> "hello 3"

#print to the output
print "hello"
print "world"
#=> helloworld

#use puts to add a newline after
puts "hello"
puts "world"
#=> hello
#=> world


Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

Sorry, comments aren't active just yet!