A script that can only print fixed text is a sign. To remember something and work with it, a script gives the thing a name. A value is a piece of information, such as the text Ada or the number 3. A variable is a name that refers to a value.
Give a value a name
name="Ada"
echo "Hello, $name!"This prints Hello, Ada!.
The first line is an assignment: it makes the name name refer to the text Ada. The rule for writing one is strict: the name, then =, then the value, with no spaces around the =.
In the second line, $name means "the value that name refers to". Before Bash runs the echo command it replaces $name with Ada. So you write the name on its own to set a variable, and with a $ in front to read it.
$name for the value it refers to. Only then does echo run, and it never sees the variable, only the finished text.A variable name may contain letters, digits and underscores (_), and must not start with a digit. Use lower-case names that say what the value is: price, first_name, total_cost.
A variable can be given a new value at any time. The name then refers to the new value, and the old one is forgotten.
colour="red"
echo "The light is $colour."
colour="green"
echo "The light is $colour."This prints The light is red. and then The light is green..
The space mistake
Putting spaces around = is the most common mistake in a first Bash script, because nearly every other programming language allows it.
name = "Ada"
echo "Hello, $name!"solution.sh: line 1: name: command not found
Hello, !Read the message as in the last lesson: line 1, the word name, "command not found". With a space after it, Bash reads name as the name of a command, with = and Ada as its arguments. No such command exists. Nothing was assigned, so the second line prints an empty space where the name should be.
That second line shows another thing to remember: a variable that was never set is empty, and using it is not an error. If a value is missing from your output, look for a misspelt variable name.
Always write "$name" inside double quotes
Whenever you read a variable, put it inside double quotation marks. Without them, Bash splits the value at its spaces and treats some characters, such as *, as special instructions, so the command can receive something different from what the variable holds. Inside double quotes the value always arrives as one unchanged piece.
title="Tea for two"
echo $title
echo "$title"This prints:
Tea for two
Tea for twoWithout quotes the value was split into three separate words and the extra spaces were lost. With quotes it is printed exactly. The next unit explains the splitting rules in depth. For now the habit is enough: every $name goes inside double quotes.
Single quotation marks are different: inside them nothing is replaced. They mean "exactly these characters".
name="Ada"
echo "Hello, $name"
echo 'Hello, $name'This prints Hello, Ada and then Hello, $name.
When a letter, digit or underscore follows straight after a variable, wrap the name in curly brackets so that Bash can see where the name ends:
fruit="apple"
echo "Two ${fruit}s"
echo "Two $fruits"This prints Two apples and then Two with nothing after it: $fruits is a different variable, which was never set, so it is empty.
Whole numbers and arithmetic
A whole number is called an integer. Bash calculates with integers inside $(( )), which is replaced by the result of the calculation.
echo "$(( 7 + 2 ))"
echo "$(( 7 - 2 ))"
echo "$(( 7 * 2 ))"
echo "$(( 7 / 2 ))"
echo "$(( 7 % 2 ))"This prints 9, 5, 14, 3 and 1. The symbols +, -, *, / and % are called operators: each one stands for an action on the values either side of it.
*means multiply./divides and drops the remainder: 7 divided by 2 is 3, remainder 1, so the answer is3.%gives that remainder:1.
As in school arithmetic, *, / and % are worked out before + and -, and round brackets come first: $(( 2 + 3 * 4 )) is 14, and $(( (2 + 3) * 4 )) is 20.
Inside $(( )) you write variable names without the $. The result can be given a name like any other value:
price=3
quantity=4
total=$(( price * quantity ))
quantity=5
echo "Total: $total"This prints Total: 12, not 15. Line 3 worked out 3 * 4 at that moment and total refers to the result, the number 12. Changing quantity afterwards does not go back and redo the calculation.
quantity do not change total.To change a variable using its own value, calculate and assign back to the same name:
score=10
score=$(( score + 5 ))
echo "Score: $score"This prints Score: 15.
Bash has no decimal arithmetic
Many languages can calculate with numbers such as 2.5. Bash cannot: it has no decimal arithmetic of its own. $(( )) works with integers only.
You can still store 2.50 in a variable and print it, because to Bash it is text made of four characters. Calculating with it fails:
price=2.50
echo "$(( price * 2 ))"solution.sh: line 2: 2.50: arithmetic syntax error: invalid arithmetic operator (error token is ".50")The message names line 2 and the value 2.50. The "error token" is the part Bash could not read as arithmetic: everything from the decimal point onwards.
The usual answer is to count in the smallest unit, so that every number is whole. Count money in pence instead of pounds, or lengths in millimetres instead of metres. To show pence as pounds, divide by 100 for the pounds and take the remainder for the pence that are left:
price=250
quantity=3
total=$(( price * quantity ))
echo "Total in pence: $total"
echo "That is $(( total / 100 )) pounds and $(( total % 100 )) pence."This prints Total in pence: 750 and That is 7 pounds and 50 pence.
Put values into a line with printf
Inside double quotes, echo joins text and values well. printf gives more control. Its first argument is a format: the line to print, with a placeholder wherever a value belongs. The values follow as further arguments, in order.
item="Notebook"
quantity=3
printf '%s: %d in stock\n' "$item" "$quantity"
printf 'Price: %d.%02d\n' 7 5This prints Notebook: 3 in stock and Price: 7.05.
%sis a placeholder for text.%dis a placeholder for an integer.%02dis an integer shown with at least two digits, with a zero in front when needed. That is how 5 pence becomes05.
The format is written in single quotes because it is meant exactly as typed; the values, which come from variables, are in double quotes. Remember that printf ends the line only where you write \n.
What you can do now
You can name text and whole numbers, read them back with a quoted "$name", calculate with $(( )), and build a line of output from text and values. You also know two silent traps: spaces around =, and a misspelt variable that is empty. In the exercises you will predict what small scripts print, then write a script that calculates a receipt.
Next: read what the user types, so that the values can come from the person running the script.