Shell Tools

Objectives

  • Discussion of last lesson.
  • Shell tool Phone Book, design.
  • Lets build the modules.
  • Lets tie this all together.
  • Lets expand the original Phone Book

Last lesson I asked you to write some shell scripts using regular expression tools. Lets look over your homeworks and discuss them. The idea is to learn by doing. Unix is not a subject for memorization, it requires facility. The best way I know to acquire facility is to use a tool.

Shell tool Phone Book.

Today we will look at using shell scripts to create a small phone book application. Lets start by outlining the project.

First lets state the goal:
Create a shell program to store names and phone numbers.
Now lets bullet the design ideas.

  1. View contents of the phone book.

    Display the contents of the phone book preceeding each entry with a line number for easy reference.

  2. Add new entries to the phone book.

    Alway add the entries to the end of the book.

  3. Find specific entries in the book.

    Ask the user for a name or number to search for, then find that entry.

  4. Delete entries from the book.

    Ask the user which line to delete, then remove that line.

OK, now lets do some archetecture design.

The data will be stored in a text file in the following format.

    Name ; phone number

Each entry will be on a separate line terminated by a line feed.

Lets build the modules

I suggest we start with a script to add entries to the phone book. Here is one I cooked up.

        #!/bin/sh
        # File: /home/john/work/bayer/training/add.sh
        # Date: Wed Feb 27 18:06:30 EST 2002
        # Last Revised: Time-stamp: <2002-02-27 18:45:45 john> maintained by emacs
        # Description: Add entries to the address book
        # ======================================================================= 

        # Name of address book
        BOOK="address-book.txt"

        # Ask the user for a name and assign to a variable
        echo -n "Name of person: " 
        read name

        # Ask the user for a phone number and assign to a variable
        echo -n "Phone number: "
        read phone

        # Echo the answers and ask for confirmation
        echo "Should I enter the values:"
        echo -e "$name ; $phone \n"
        echo -n "y/n: "
        read answer

        if [ "$answer" == "y" ] 
        then
            # Write the values to the address book
            echo "$name ; $phone" >>$BOOK
        else
            # Give the user a message
            echo "$name ; $phone NOT written to $BOOK"
        fi

        exit 0

Now we have the ability to add entries to our book. Next we should build something to list the contents of our book.

        #!/bin/sh
        # File: /home/john/work/bayer/training/list.sh
        # Date: Wed Feb 27 18:04:46 EST 2002
        # Last Revised: Time-stamp: <2002-02-27 18:17:38 john> maintained by emacs
        # Description: List the entries in the address book with line numbers. 
        # ======================================================================= 

        BOOK="address-book.txt" 

        # Display the format before the entries
        echo "Line Number:   Name  ;  Phone Number"

        # Print the book with line numbers and paused with less
        nl --number-separator=":    " $BOOK | less 

Now suppose we want to search the address book to find a specific entry?

        #!/bin/sh
        # File: /home/john/work/bayer/training/find.sh
        # Date: Wed Feb 27 18:50:13 EST 2002
        # Last Revised: Time-stamp: <2002-02-27 18:53:00 john> maintained by emacs
        # Description: Find a specific line in the file.
        # ======================================================================= 

        BOOK="address-book.txt"

        # Ask the user what to look for.
        echo -n "What person or number are you seeking: "
        read find

        # Print the header before the answer
        echo "Name ; Phone number"
        grep -i $find $BOOK

Lastly in the tool set, build a tool to delete a specific entry in the phone book.

        #!/bin/sh
        # File: /home/john/work/bayer/training/del.sh
        # Date: Wed Feb 27 18:21:33 EST 2002
        # Last Revised: Time-stamp: <2002-02-27 18:47:49 john> maintained by emacs
        # Description: Delete the line specified by the user.
        # ======================================================================= 

        BOOK="address-book.txt"

        # Ask the user which line to delete
        echo -n "Which line should I delete: "
        read number

        # Rename the file before deleting
        mv $BOOK boo.txt

        # Add line numbers and delete against that number
        nl --number-separator=":" boo.txt | grep -v $number: | awk -F: '{print $2}' |  tee $BOOK

Lets tie this all together

OK, now that we have the individual shell scripts to perform the functions, why not make a master script to call the individual scripts. Here is what I created in the class.

        #!/bin/sh
        # File: d:/home/john/tmp/phone.sh
        # Date: Thu 28 Feb 2002 10:35:24 Eastern Standard Time
        # Last Revised: Time-stamp: <2002-02-28 10:46:15 exmxm> maintained by emacs
        # Description: Master script for phone book program
        # ======================================================================= 

        # Name of address book
        BOOK="address-book.txt"

        exit=0

        while [ $exit -ne 1 ]
        do
            echo "What operation do you want?"
            echo -e "add, list, find, del, exit: "
            read answer

            if [ "$answer" = "add" ]
            then
                ./add.sh
            elif [ "$answer" = "list" ]
            then
                ./list.sh
            elif [ "$answer" = "find" ]
            then
                ./find.sh
            elif [ "$answer" = "del" ]
            then
                ./del.sh
            elif [ "$answer" = "exit" ]
            then
                exit=1
            else
                echo "I do not understand the command."
            fi
        done

        exit 0

Lets expand the original Phone Book

OK, we are going to take the original shell scripts for the phone book program and expand them. Lets take a minute and define the improvements wanted.

  • Add street, city, state, and zip code to records
  • Display the records in a more common format.
  • Add the ability to search only specified fields

New Version of Phone Book

Ok here is a listing of the Design changes to be made. I will then show the code that was produced.

In the phone.sh file, which will be renamed to phone2.sh, clear the screen before printing the user prompt. This will give it a cleaner look. In addition, define the storage file here and not in the individual files.

#!/bin/sh
# File: /dosd/home/john/tmp/phone2.sh
# Date: Wed Mar  6 08:17:29 EST 2002
# Last Revised: Time-stamp: <2002-03-07 09:28:14 john> maintained by emacs
# Description: Master script for phone book program
# Revised for the second version of the phone book.
# ======================================================================= 

# Name of address book
BOOK="address-book2.txt"

export BOOK

exit=0

while [ $exit -ne 1 ]
do
    clear
    echo "What operation do you want?"
    echo -e "add, list, find, del, exit: "
    read answer

    if [ "$answer" = "add" ]
    then
        ./add2.sh
    elif [ "$answer" = "list" ]
    then
        ./list2.sh
    elif [ "$answer" = "find" ]
    then
        ./find2.sh
    elif [ "$answer" = "del" ]
    then
        ./del2.sh
    elif [ "$answer" = "exit" ]
    then
        exit=1
    else
        echo "I do not understand the command."
        sleep 5
    fi
done

exit 0

In the add2.sh script, add additional requests for the additional data, street, city, state, and zip. Once the data is entered, display the results in a more normal format. Paying attention to the look of the input and output will make the program seem more professional. At the end of any output, besure to pause for the user to be able to read the output before clearing it.

#!/bin/sh
# File: /dosd/home/john/tmp/add2.sh
# Date: Wed Mar  6 08:19:36 EST 2002
# Last Revised: Time-stamp: <2002-03-06 09:03:48 john> maintained by emacs
# Description: Add entries to the address book
# Revisied: Modifyed for the second version of phone book
# ======================================================================= 

# echo "Book = $BOOK"
echo -e "\n ======== Beginning Adding Addresses =======\n\n"

# Ask the user for a name and assign to a variable
echo -n "Name of person: " 
read name

# Ask for the street address
echo -n "Street Address: "
read street

# Ask for the city
echo -n "City: "
read city

# Ask for the state address
echo -n "State: "
read state

# Ask for the zip address
echo -n "Zip Code: "
read zip

# Ask the user for a phone number and assign to a variable
echo -n "Phone number: "
read phone

# Echo the answers and ask for confirmation
echo "Should I enter the values:"
echo -e " $name \n $street \n $city, $state, $zip \n $phone \n"
echo -n "y/n: "
read answer

# Convert the answer to lower case
fixedanswer=`echo $answer | tr "A-Z" "a-z"`;

if [ "$fixedanswer" = "y" ] 
then
    # Write the values to the address book
    echo "$name;$street;$city;$state;$zip;$phone" >>$BOOK
    echo "Added the entry OK"
    sleep 5
else
    # Give the user a message
    echo -e " $name \n $street \n $city, $state, $zip \n $phone \n NOT written to $BOOK"
    sleep 5
fi

exit 0

In the file list2.sh, provide a more normal display showing the output in a more natural format. Pass the user information on how to end the display and return to the top level program.

#!/bin/sh
# File: /home/john/work/bayer/training/list.sh
# Date: Wed Feb 27 18:04:46 EST 2002
# Last Revised: Time-stamp: <2002-03-06 09:07:04 john> maintained by emacs
# Description: List the entries in the address book with line numbers. 
# ======================================================================= 

# Read each line in the book and display

(awk -F ";" '{printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n==========================\n\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK ; echo "Press Q to Quit and return to the menu." ) | less

# Display the format before the entries
#echo "Line Number:   Name  ;  Phone Number"

# Print the book with line numbers and paused with less
#nl --number-separator=":    " $BOOK | less 

In the find2.sh script, allow the user to select which field to search, and what to search for. When the result is found, format the output before displaying.

#!/bin/sh
# File: /dosd/home/john/tmp/find2.sh
# Date: Wed Mar  6 09:07:47 EST 2002
# Last Revised: Time-stamp: <2002-03-07 09:30:03 john> maintained by emacs
# Description: Find a specific line in the file.
# Revised for a more complex search capability
# ======================================================================= 

# Ask the user what to look for.
echo -n -e "What field would you like to search: \n\tname, street, city, state, zip, or phone: "
read field

echo -n "In the field = \"$field\", what string should I find? "
read string 

# Find the string in the selected field
case $field in  

    "name" ) # Search for a specific name
             awk -v var=$string -F ";" '$1 ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK | less
             # result=`awk -F ";" '{printf "%d: %s\n", NR, $1}' $BOOK | grep -i $string | \
                     #awk -F ":" '{print $1}' `
             ;;

    "street" ) # Search for a specific name
               awk -v var=$string -F ";" '$2 ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK | less
              ;;

    "city" ) # Search for a specific name
             awk -v var=$string -F ";" '$3 ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK | less
             ;;

    "state" ) # Search for a specific name
              awk -v var=$string -F ";" '$4 ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK | less
             ;;

    "zip" ) # Search for a specific name
            awk -v var=$string -F ";" '$5 ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK | less
             ;;

    "phone" ) # Search for a specific name
              awk -v var=$string -F ";" '$6 ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK | less
             ;;

    "*" ) # Search pattern not recognized
          echo "I did not understand your field name";
          ;;
esac
 
# echo "Result = $result";

# if [ "$result" != "" ]
#     then
#     for number in $result
#     do 
#        awk -v val=$number  -F ";" 'NR == val {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK
#     done
# else
#     echo "Did not find $string in $field"
# fi

# echo "Past Case"
# sleep 5;

exit 0

Finally in the del2.sh script, the only change is the remove the reference to the storage location.

#!/bin/sh
# File: /home/john/work/bayer/training/del2.sh
# Date: Wed Feb 27 18:21:33 EST 2002
# Last Revised: Time-stamp: <2002-03-07 18:15:04 john> maintained by emacs
# Description: Delete the line specified by the user.
# ======================================================================= 


# Ask the user which line to delete
echo -n "Which line should I delete: "
read number

# Display the record selected
awk -v var=$number -F ";" 'NR ~ var {printf "Record: %d\n\t%s\n\t%s\n\t%s, %s, %s\n\t%s\n", NR, $1, $2, $3, $4, $5, $6}' $BOOK

# Ask the user if this is correct before deleting.
echo -n "Is this the correct record to delete? (y/n): "
read answer

# Lower case the answer and check
fixedanswer=`echo $answer | tr "A-Z" "a-z"`;
if [ "$fixedanswer" = "y" ] 
then

    # Rename the file before deleting
    mv $BOOK boo.txt

    # Add line numbers and delete against that number
    nl --number-format=rz --number-separator=":" boo.txt | grep -v 0$number: | awk -F: '{print $2}' |  tee $BOOK

else

    echo "Did not delete the record"
    sleep 5

fi

Home Work

This week I would like you to extract the scripts displayed above. Place them in a local directory and see if you can improve them. Try making changes to see what happens. One of the best ways to learn about something is to try modifying it.

No, this phone book is not a replacement for a real phone book program. But in the same vane, once you start to learn the possibilities of scripts, you will understand one of the most misunderstood parts of computing. Let the computer do the repetative tasks for you. One of the original uses of computers was Batch Processing. By teaching the computer to perform tasks for you, you gain the ability to have it be a real helper, not just a word processor and a game machine.



Written by John F. Moore

Last Revised: Wed Oct 18 11:01:31 EDT 2017

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
HTML5 Powered with CSS3 / Styling, and Semantics