Skip to content
Lesson 2 of 14

Step 1 of 5 · Reading · ~3 min

Learn

Getting Started

Variables

By the end of this lesson you can store text in a variable, read it back safely, join variables into longer strings, and read lines of input into variables. Bash variables hold text and nothing else: no integers, no objects. (Arithmetic is a special context you will meet next lesson.)

Rule 1: no spaces around =

city="Oslo"        # correct
city = "Oslo"      # wrong

You know from last lesson that bash cuts a line into words and treats the first word as a command. The second line is the command city with two arguments, = and Oslo, and bash replies city: command not found. Assignment is name=value with nothing between the parts.

Rule 2: $ to read, nothing to write

greeting="Hello"
echo "$greeting"          # Hello
greeting="$greeting!"     # write without $, read with $
echo "$greeting"          # Hello!

Bash substitutes the variable's text into the line before the command runs, so the line you wrote is a template and the line that runs is the expanded result.

A variable name is as long as the letters, digits and underscores that follow the $. When your text continues with more of those characters, mark the end with braces:

pet="cat"
echo "$pets"       # prints an empty line: bash looked up a variable called pets
echo "${pet}s"     # cats

Quote every expansion

An unquoted expansion is split into words on whitespace, and each word that contains * or ? is then matched against file names.

song="Let it   be"
echo $song         # Let it be      (three spaces became one)
echo "$song"       # Let it   be    (kept)

The same mechanism destroys data: with file="my notes.txt", rm $file runs rm my notes.txt and deletes two files you did not mean. rm "$file" passes one argument. The discipline is mechanical: write "$var" every time, unless you can say why you want splitting.

Double quotes allow expansion. Single quotes suppress it: '$song' is a dollar sign followed by four letters.

Reading input into variables

read -r first rest

read takes one line from stdin and assigns it to the names you give. With several names, the first words go to the first names and the remainder goes to the last one. Leading and trailing whitespace is trimmed, inner spacing is kept, and -r stops backslashes from being treated as escapes (always write it). With the line Ada Lovelace of London , first is Ada and rest is Lovelace of London.

When the input has one value per line, use one read per value. A single read a b against two lines leaves b empty, which is the classic wrong answer.

Environment variables, briefly

Your script inherits variables such as $HOME and $PATH from whatever launched it. By convention ALL_CAPS names are for inherited or exported configuration and lowercase names are for your script's own use. export level=3 hands a variable down to programs your script starts.

Common mistakes

  • Spaces around =. count = 5 runs a command named count.
  • A $ on the left. $count=5 expands $count first and then tries to run the result as a command.
  • Missing braces. "$pet_old" reads a variable named pet_old, not pet followed by _old, and silently prints nothing.
  • Unquoted expansion. It collapses runs of spaces and can match file names, so output is wrong only on some inputs.

Your exercise

Build a release name from two values you read, using a variable to hold the shared part and printing it in two forms. The most likely mistake is a name that bash reads as a longer variable than you meant.

Up nextArithmeticGetting Started

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…