Getting older, not necessarily wiser!
In this installment we are going to up the complexity a little. We will be collecting input from the user while the script is running, and introducing a couple of new structures (while loop and case).
Nothing that is to bizarre. The program flow and logic should still be straight forward and easy to follow. I have, on occasion, noticed on a lot of scripts I look at have some fairy complex logic, structure, and flow. The script we will review today could be cut down to less than half the length it is, but it would not be as easy to follow.
These are text files after all and I would be looking at the difference between 1.7 KB and 0.8 KB. Not a lot by today’s standard. So I prefer to make the script easier to follow, even if it takes up a few extra KB.
Today’s scrip is a simple calculator script that provides basic instruction to the user, gets and validates user input (asking for reentry if incorrect), and then outputs results. I am posting the script, after which we will go thought it. This one is a bit longer than previous scripts.
#!/bin/bash # Name: user_math Version: 1 # Author: RetiredTechie Date: 11 SEP 2022 # # Description: Get user input to perform some basic math operations # Set some variable values before doing anything esle NUMBER1="0" NUMBER2="0" NUMBER3="0" OPERATOR="0" # Print out instructions for the user printf "%b" "\nBASH SIMPLE CALCULATOR SCRIPT\n\n" printf "%b" "This script will perform simple calculations based on\n" printf "%b" "three pieces of user input. These are as follows:\n\n" printf "%-10s %s\n" "Entry" "Type" printf "%-11s %s\n" "----------" "-----------------------" printf "%-11s %s\n" "Digit 1" "An integer from 1 to 9" printf "%-11s %s\n" "Digit 2" "An integer from 1 to 9" printf "%-11s %s\n" "Operator" "Addition [+]" printf "%-11s %s\n" " " "Subtraction [-]" printf "%-11s %s\n" " " "Multiplication [x]" printf "%-11s %s\n" " " "Division [/]" printf "%b" "\n" # Collect User input while [ $NUMBER1 -lt 1 ]; do # While loop cycles though until # valid input received. read -p "Digit 1: " NUMBER1 # Restates input requirements on # bad input if ! echo $NUMBER1 | grep -Eq '^[1-9]*$'; then NUMBER1="0" echo "Must be an integer between 1 and 9" fi done while [ $NUMBER2 -lt 1 ]; do read -p "Digit 2: " NUMBER2 if ! echo $NUMBER2 | grep -Eq '^[1-9]*$'; then NUMBER2="0" echo "Must be an integer between 1 and 9" fi done while ! echo $OPERATOR | grep -Eq '^[+,--,x,/]$' > /dev/null; do read -p "Operator: " OPERATOR if ! echo $OPERATOR | grep -Eq '^[+,--,x,/]$'; then OPERATOR="0" echo "Must be +, -, x, or /" fi done echo # Do calculation and output results case $OPERATOR in +) # Case operator for each instance NUMBER3=$(($NUMBER1+$NUMBER2)) echo $NUMBER1 "+" $NUMBER2 "=" $NUMBER3 ;; -) NUMBER3=$(($NUMBER1-$NUMBER2)) echo $NUMBER1 "-" $NUMBER2 "=" $NUMBER3 ;; x) NUMBER3=$(($NUMBER1*$NUMBER2)) echo $NUMBER1 "x" $NUMBER2 "=" $NUMBER3 ;; *) # catch all end operator, whatever is left NUMBER3=$(($NUMBER1/$NUMBER2)) echo $NUMBER1 "/" $NUMBER2 "=" $NUMBER3 ;; esac echo exit 0
Skipping over items form previous posts, we start at Line 8. Here we are declaring some variables we will be using and assigning them a value. Some might argue we do not need to do this in a shell script, but to me it makes the flow easier to follow.
After assigning some variables we print out user instructions. I used printf instead of echo, to demonstrate some of the formatting options. We could have done the same thing with echo, but if you do a lot of scripting for different distributions you will find that sometimes the echo command can behave differently than expected.
We then use while – done loops to collect user input. We are using one of the variables we defined earlier to contorl the loop. It must be set to a value greater than 1 to exit the loop.
We use an if – fi statement and a regular expression to evaluate user input. If it does not match our input requirements, we send the user a message reminding them what the requirement is, and give them a chance to reenter. We also reset the control variable to zero.
For each of the three user inputs we perform a similar loop test.
Since we only allow four possible calculations, we use a case statement. In a case statesmen we select a variable, then can match on specific patterns, which in turn executes only the specific code for that pattern.
Note that on the last match we use a star (*). This technically can match any pattern, and is a catchall at the end of a case statement. We could have used the divide symbol here. But in practice the last part of a case should be what to do if nothing else matches.
This script introduced while and case, as well as collecting user input. While the code here is a little longer than before, you should be able to follow the flow without any problems.
In our next installment we will look at functions inside a bash script.
Shell or Terminal? Shell Scripting – Part 1
Simple Script Example! Shell Scripting – Part 2
Command Line Arguments! Shell Scripting Part 3
User Input! Shell Scripting Part 4
Add New Comment