Книга: The Linux Command Line
Назад: 26. Top-Down Design
Дальше: 31. Flow Control: Branching with case

and variable is the name of one or more variables used to hold the input value. If no variable name is supplied, the shell variable REPLY contains the line of data.

.

-d delimiter

The first character in the string delimiter is used to indicate end of input, rather than a newline character.

-e

Use Readline to handle input. This permits input editing in the same manner as the command line.

-n num

Read num characters of input, rather than an entire line.

-p prompt

Display a prompt for input using the string prompt.

-r

Raw mode. Do not interpret backslash characters as escapes.

-s.

Using the various options, we can do interesting things with read. For example, with the -p option, we can provide a prompt string:

.

With our new ability to have keyboard input comes an additional programming challenge: validating input. Very often the difference between a well-written program and a poorly written one lies in the program’s ability to deal with the unexpected. Frequently, the unexpected appears in the form of bad input. We did a little of this with our evaluation programs in the previous chapter, where we checked the values of integers and screened out empty values and non-numeric characters. It is important to perform these kinds of programming checks every time a program receives input to guard against invalid data. This is especially important for programs that are shared by multiple users. Omitting these safeguards in the interests of economy might be excused if a program is to be used once and only by the author to perform some special task. Even then, if the program performs dangerous tasks such as deleting files, it would be wise to include data validation, just in case.

Here we have an example program that validates various kinds of input:

#!/bin/bash  # read-validate: validate input   invalid_input () {         echo "Invalid input '$REPLY'" >& 2         exit 1 }  read -p "Enter a single item > "  # input is empty (invalid) [[ -z $REPLY ]] && invalid_input  # input is multiple items (invalid) (( $(echo $REPLY | wc -w) > 1 )) && invalid_input  # is input a valid filename? if [[ $REPLY =˜ ^[-[:alnum:]\._]+$ ]]; then         echo "'$REPLY' is a valid filename."         if [[ -e $REPLY ]]; then                 echo "And file '$REPLY' exists."         else                 echo "However, file '$REPLY' does not exist."         fi          # is input a floating point number?         if [[ $REPLY =˜ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then                 echo "'$REPLY' is a floating point number."         else                 echo "'$REPLY' is not a floating point number."         fi          # is input an integer?         if [[ $REPLY =˜ ^-?[[:digit:]]+$ ]]; then                 echo "'$REPLY' is an integer."         else                 echo "'$REPLY' is not an integer."         fi else         echo "The string '$REPLY' is not a valid filename." fi

This script prompts the user to enter an item. The item is subsequently analyzed to determine its contents. As we can see, the script makes use of many of the concepts that we have covered thus far, including shell functions, [[ ]], (( )), the control operator &&, and if, as well as a healthy dose of regular expressions.

A common type of interactivity is called menu driven. In menu-driven programs, the user is presented with a list of choices and is asked to choose one. For example, we could imagine a program that presented the following:

Please Select:  1. Display System Information 2. Display Disk Space 3. Display Home Space Utilization 0. Quit  Enter selection [0-3] >

Using what we learned from writing our sys_info_page program, we can construct a menu-driven program to perform the tasks on the above menu:

#!/bin/bash  # read-menu: a menu driven system information program  clear echo " Please Select:  1. Display System Information 2. Display Disk Space 3. Display Home Space Utilization 0. Quit " read -p "Enter selection [0-3] > "  if [[ $REPLY =˜ ^[0-3]$ ]]; then         if [[ $REPLY == 0 ]]; then                 echo "Program terminated."                 exit         fi         if [[ $REPLY == 1 ]]; then                 echo "Hostname: $HOSTNAME"                 uptime                 exit         fi         if [[ $REPLY == 2 ]]; then                 df -h                 exit         fi         if [[ $REPLY == 3 ]]; then                 if [[ $(id -u) -eq 0 ]]; then                         echo "Home Space Utilization (All Users)"                         du -sh /home/*                 else                         echo "Home Space Utilization ($USER)"                         du -sh $HOME                 fi                 exit         fi else         echo "Invalid entry." >&2         exit 1 fi

This script is logically divided into two parts. The first part displays the menu and inputs the response from the user. The second part identifies the response and carries out the selected action. Notice the use of the exit command in this script. It is used here to prevent the script from executing unnecessary code after an action has been carried out. The presence of multiple exit points in a program is generally a bad idea (it makes program logic harder to understand), but it works in this script.

© RuTLib.com 2015-2018