Skip to content
Variables
step 1/5

Reading — step 1 of 5

Learn

~3 min readGetting 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

Two reads and an arithmetic expansion (formally introduced next lesson):

read a
read b
echo "$((a + b))"

Quoting habit check: the $((…)) result has no spaces, but wrapping it in quotes anyway costs nothing and keeps the reflex strong. Three lines, two rules, one habit — that's bash variables.

Discussion

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

Sign in to post a comment or reply.

Loading…