How to Write Interactive Shell Scripts

Input and Output in a Script

While some scripts run without any interaction with the user, many scripts require input from the user or give output to the user as the script is running.

Advantages of no interaction include:

  • The script runs the same way every time.
  • The script can run in the background

Advantages of user interaction include:

  • The script is more flexible.
  • The user can customize the script as it runs.
  • The script can report its progress as it runs

The Korn Shell Print Statement

Use the print statement to provide output. Use it wherever you would use the echo statement. It is more versatile than the echo statement. The print statement has several options:

Examples of Using the echo Statement

The following are examples of the echo options and special characters displayed on the command line. Experiment with these to see how they work. These examples show that you have an alternative to the Korn shell-specific print statement. Although it looks as though the last example does not work, this is only because the shell overwrites the closing square bracket when the next command line prompt is displayed.

$ echo "Hello there.\nHow are you?"
Hello there.
How are you?
$ echo "Hello there.\\nHow are you?"
Hello there.\nHow are you?”
$ echo "-2 was the temperature this morning."
-2 was the temperature this morning.
$ echo "No newline printed here. \c"
No newline printed here. $
$ echo "Hello\tout\tthere!"
Hello   out     there!
$ echo "\007Listen to me!"
Listen to me!
$ echo "Overwrite\b the 'e' in 'Overwrite'."
Overwrit the 'e' in 'Overwrite'.
$ echo "Type a lette [ ]\b\b\c"
Type a letter [$

The read Statement

The counterpart to the print or echo statement is the read statement. The read statement reads input typed in by the user from the keyboard, or it reads a line from a file.

  • The input is parsed (broken down) into tokens. A token is any group of consecutive characters that do not contain white spaces. Thus, the first token begins with the first non-white-space character and ends when a white-space character is encountered. The second token begins with the next non-white-space character and ends with the first white-space character thereafter, and so on. White space can be included if quotes are used around the token.
  • The read statement continues reading characters until a newline character is encountered.
  • The read statement uses the contents of the IFS variable as token delimiters. By default, the values are white space; however, you can change this to include other characters, such as commas, colons, or other field separators.
  • The first token is saved in the first variable name following the read statement, the second token is saved in the second variable, and so on. If there are more tokens than variables supplied to read, the last variable holds all remaining tokens.

If there are no variable names supplied to the read statement, the Korn shell puts the values read in the REPLY variable. The Bourne shell returns an error.

Examples of Using the read Statement

In the following example, the number of variables supplied to read matches the number of tokens typed on the command line.

$ read var1 var2 var3
abc  def  ghi

$ echo $var1
abc

$ echo $var2
def

$ echo $var3
ghi

In the following example, the number of variables supplied to read is less than the number of tokens typed on the command line

$ read num string junk
134 bye93;alk the rest of the line is put in 'junk'

$ echo $num
134

$ echo $string
bye93;alk

$ echo $junk
the rest of the line is saved in 'junk'

In the following example, the number of variables supplied to read is more than the number of tokens typed on the command line.

$ read token1 token2
one

$ echo $token1
one

$ echo $token2

If variable names are not supplied to read when using Korn shell, it populates the REPLY variable with the user input, as in the following example:

$ read
What is this saved in?

$ echo $REPLY
What is this saved in?

If variable names are not supplied to read when using Bourne shell, it gives an error message, as in the following example:

$ read
read: missing arguments

Capturing a Command Result

Use the read statement to capture a command result. To assign the command result to a variable:

var=`ls -l /etc/passwd`

You can capture the command output into a file and then use the read statement to assign the values to variables as shown below:

$ ls -l /etc/passwd > file
$ read a b c d e f g h < file

$ echo $a
-rw-r--r-

$ echo $b
1

$ echo $h
16:20 /etc/passwd

Alternatively, you can pipe the output of a command to the read statement:

# ls -l /etc/passwd | read x y z p q r

# echo $x
-rw-r--r-

# echo $y 1

# echo $z
root

Printing a Prompt

This example shows how to prompt a user for some input using a \c in the output string. A read statement obtains the input. The input is read and saved in variables using the read statement. An extra variable, junk, is supplied with both read statements to pick up any extra input by the user. The input is used in a message that prints to the screen with the echo statement.

$ cat io1.sh
#!/bin/sh

# Script name: io1.sh

# This script prompts for input and prints messages
# involving the input received.

echo "Enter your name: \c" read name junk

echo "Hi $name, how old are you? \c"
read age junk

echo "\n\t$age is an awkward age, $name,"
echo "  You’re too old to depend on your parents,"
echo "and not old enough to depend on your children."
$ ./io1.sh
Enter your name: Murdock.
Hi Murdock, how old are you? 25
    25 is an awkward age, Murdock.
  You’re too old to depend on your parents,
and not old enough to depend on your children.

Similarly, you could prompt for input using the print statement with the -n option. The -n option leaves the cursor at the end of the text line.

$ cat io2.ksh
#!/bin/ksh

# Script name: io2.ksh

# This script prompts for input and prints messages
# involving the input received.

print -n "Enter your name: "
read name junk

print -n "Hi $name, how old are you? "
read age junk

print "\n\t$age is an awkward age, $name,"
print "   You’re too old to depend on your parents,"
print "and not old enough to depend on your children."
$ ./io2.ksh
Enter your name: Murdock. Hi Murdock, how old are you? 25
    25 is an awkward age, Murdock.
  You’re too old to depend on your parents,
and not old enough to depend on your children.

Prompting for Input – Korn Shell Shortcut

When you use one variable with the read statement, you can put the prompt for the input within the read statement itself. The syntax is:

read var?"prompt"

Although this prompting facility is available in the Korn shell, it’s better to use either echo or print to display a prompt message. The echo and print statements are more flexible because they can display many text lines as one output string. It’s also more difficult to debug a script when combining the read statement with a prompt string in one statement line. The following example shows how to put the prompts into read statements instead of using print statements. The output from running the script is the same as the output from the execution of the script io2.ksh script.

$ cat io3.ksh
#!/bin/ksh

# Script name: io3.ksh

# This script prompts for input and prints messages
# involving the input received.

read name?"Enter your name: "

read age?"Hi $name. How old are you? "

print "\n\t$age is an awkward age, $name,"
print "   You’re too old to depend on your parents,"
print "and not old enough to depend on your children."
$ ./io3.ksh
Enter your name: Murdock
Hi Murdock.  How old are you? 25

    25 is an awkward age, Murdock.
  You’re too old to depend on your parents,
and not old enough to depend on your children.

When you put the prompt for input into the read statement, you can supply an extra variable to pick up extra input by the user, for example:

$ read name?" Enter your name:
" Enter your name: John Murdock

$ print $name
John Murdock
$ read name?" Enter your name: " more
Enter your name: John Murdock

$ print $name
John

$ print $mor
Murdock