Skip to content
Lesson 2 of 14

Step 1 of 5 · Reading · ~3 min

Learn

Getting Started

Variables

Bash variables hold text. Not integers, not objects — strings, always (arithmetic is a special context you'll meet next lesson). The syntax has two rules that break everyone arriving from real languages, so let's break them on purpose, now, where it's cheap.

Rule 1: no spaces around =

name="Ada"        # correct
name = "Ada"      # WRONG — bash runs the command `name` with args `=` and `"Ada"`

Remember words-and-commands from last lesson? name = "Ada" parses as command name — bash helpfully reports name: command not found, a bizarre error until you know why it happens, obvious forever after. Assignment is name=value, welded together.

Rule 2: $ to read, nothing to write

greeting="Hello"
echo "$greeting"        # read with $
greeting="$greeting!"   # write without $, read with $ — both in one line

$name (or ${name} when you need boundaries: "${file}_backup" — without braces bash would look for a variable named file_backup) substitutes the variable's text into the line before the command runs. That "before" is the key to bash's whole execution model: the line you wrote is not the line that runs; it's a template that gets expanded.

The rule that separates pros from postmortems: quote your variables

file="my report.txt"
rm $file       # runs: rm my report.txt → deletes "my" and "report.txt" (!!)
rm "$file"     # runs: rm with ONE argument → deletes the right file

Unquoted $file gets substituted, then split into words on whitespace. A filename with a space becomes two arguments; a variable containing * gets glob-expanded into every file in the directory. This is not a rare edge case — it's the single most common bash bug in existence, and it has destroyed real data (search "steam bash bug" someday). The discipline is mechanical: always write "$var", never bare $var, unless you can articulate why you want word-splitting. Double quotes allow substitution ("Hello, $name"); single quotes suppress it ('$name' is literally a dollar sign and four letters).

Reading input

read a          # read one LINE from stdin into a
read b          # read the next line
echo "$((a + b))"

read grabs a line and assigns it. Grader input often puts one value per line — two reads, as above. Multiple values on one line split across names: read x y assigns first word to x, rest to y. Check the exercise's input format examples and pick accordingly; a read a b against line-separated input leaves b empty, which is this exercise's classic wrong answer.

Environment variables, briefly

Your script inherits variables from the shell that launched it — $HOME, $PATH, $USER — and by convention ALL_CAPS names are for those and exported config; lowercase names are for your script's own locals. export mine=1 pushes a variable down into programs your script launches. That's the whole environment model in three sentences, and it's why config-by-env-var (the pattern every deployment system uses) works.

Your exercise: Sum Two Numbers

The starter already does the reading: two reads, one per line, matching the input format. What is left is a single line. The values arrived as text, so they have to travel through an arithmetic context to become numbers -- the $(( )) form previewed above, formally yours next lesson -- and the result comes back out as text for echo to print.

Quoting habit check: an arithmetic result never contains spaces, so quoting it changes nothing here. Quote it anyway. Two rules and one habit is the whole of bash variables, and the habit is the part that survives contact with real filenames.

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…