CodeRigor

LESSON

Read what the user types

Ask a question, read the line the user types with read -r, calculate with the answer and build scripts that prompt, read, compute and print.

So far every value was written into the script. A useful script asks the person running it for information and responds to what they type. The person running a program is called its user, and what they give the program is its input.

read takes one line

The command read waits for the user to type a line and press Enter, and stores that line in a variable. A message that tells the user what to type is called a prompt.

Bash
echo "What is your name?"
read -r name
echo "Hello, $name!"

If the user types Ada, the whole conversation on the screen looks like this:

Text
What is your name?
Ada
Hello, Ada!

Three details:

  • read is followed by the name of the variable to fill, written without a $. As with an assignment, you use the bare name to set a variable and $name to read it.
  • -r is an option: a setting that starts with a dash and changes how a command behaves. -r tells read to take the line exactly as typed. Without it, read treats the backslash character \ as special. Write read -r every time.
  • The second line of the conversation, Ada, was typed by the user. The script printed only the first and third lines.

Running scripts that read input

This example has no Edit & run button, because a button cannot stop and wait for you to type. Run it in the Bash playground instead:

  1. Copy the script into the editor.
  2. Open Standard input below the output and type what the user would type, one answer per line. For this script, type Ada.
  3. Press Run.

"Standard input" is the name programmers use for the stream of text that a program reads, which is normally the keyboard. On this site the script runs on our server, so you provide the typed lines in advance. Because nobody types on the screen there, the output shows only what the script printed: What is your name? and Hello, Ada!. The script has still read Ada exactly as it would from a keyboard.

On your own computer, bash hello.sh behaves exactly as the conversation above shows: the script stops at each read and waits for you.

A prompt on the same line

Often the answer looks better on the same line as the question. echo always ends its line, so use printf without \n, and end the prompt with a space:

Bash
printf 'What is your name? '
read -r name
echo "Hello, $name!"
Text
What is your name? Ada
Hello, Ada!

Both styles are common. The exercises in this unit print each prompt on a line of its own with echo, because that is clearer to check.

In other people's scripts you may see read -r -p "What is your name? " name. The -p option shows a prompt, but only when a person is typing at a terminal. When the input is supplied in advance, as it is on this site, -p shows nothing. A prompt printed with echo or printf behaves the same everywhere.

What read stores is text

To Bash, every value is text. When the user types 36, the variable holds two characters, a 3 and a 6. Inside a string those characters are only pasted in:

Bash
answer="36"
echo "$answer + 1"
echo "$(( answer + 1 ))"

This prints 36 + 1 and then 37. The first line is a string with a value placed in it; no arithmetic happens. Inside $(( )) Bash reads the digits as the number thirty-six and calculates. So in Bash, turning typed text into a number takes no extra step, but the calculation must be inside $(( )).

From typed text to a number you can calculate with
start / 4 ⇄ code
The user types the two characters 3 and 6. read stores them as text. Inside $(( )) Bash reads that text as the number 36, and only there does + 1 mean arithmetic.
From typed text to a number you can calculate with
The user types the two characters 3 and 6. read stores them as text. Inside $(( )) Bash reads that text as the number 36, and only there does + 1 mean arithmetic.
Bash
echo "How old are you?"
read -r age
next_year=$(( age + 1 ))
echo "Next year you will be $next_year."

The shape of an interactive script

Most small programs follow the same four steps: prompt, read, compute, print.

Prompt, read, compute, print
start / 4
Ask a question, read the answer, calculate, then show the result. Longer scripts repeat this shape.
Prompt, read, compute, print
Ask a question, read the answer, calculate, then show the result. Longer scripts repeat this shape.

Here is the whole shape in one script. It asks for the sides of a rectangle and prints its area. Each read takes the next line the user types, so two questions need two read commands.

Bash
echo "Width in metres?"
read -r width
echo "Height in metres?"
read -r height
area=$(( width * height ))
echo "Area: $area square metres"

With 3 and 4 typed as the two answers, it prints the two questions and then Area: 12 square metres. Try it in the playground with two lines of standard input.

Four things that go wrong

Forgetting $(( )). There is no error message; the output is the giveaway. If you see 36 + 1 where you expected 37, the calculation is sitting inside a string.

A $ after read. read -r $age is wrong: it should be read -r age. Bash replaces $age with its value, which is empty at that point, so read is given no variable name and age stays empty. Again there is no message, only a missing value in the output.

Text that is not a whole number. If the user answers 3 apples to the age script above, the arithmetic fails and the script stops:

Text
solution.sh: line 3: 3 apples: arithmetic syntax error in expression (error token is "apples")

Read it in parts: line 3 is the line with $(( )); 3 apples is the value Bash was asked to calculate with; the "error token" is the part it could not read as arithmetic. The typed text was the problem, and line 3 is where it was noticed. A decimal such as 3.5 gives the same kind of message, because Bash has no decimal arithmetic.

A single word is worse, because it gives no message at all. If the user types ten, the script prints Next year you will be 1. Inside $(( )) a word is taken as a variable name, and a variable that was never set counts as 0. For now, assume the user types sensible whole numbers; later courses show how to check.

Reading more than was typed. On this site, a read that finds no line left stores nothing, and the script carries on with an empty variable. In arithmetic an empty variable counts as 0. If a result looks as if an answer was ignored, check that Standard input has one line for every read.

What you can do now

You can prompt the user, read a line, calculate with it and print a result that depends on what was typed. In the exercises you will predict what scripts print from given answers, then write a script that holds a short conversation.

Next: make decisions, so that a script can respond differently to different answers.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →