To get us going on shell scripting, here are some variations of the “Guess a number” script we started writing in class.
Look through them, try them out, and make sure everything is making sense (if not, PLEASE ASK).
#!/bin/bash # # guess.sh - guess the number the computer has chosen (1 try) # value=`bc -q <<< "(${RANDOM} % 10) + 1"` echo -n "Pick a value (1-10): " read num if [ "${num}" -eq "${value}" ]; then echo "You guessed correctly!" else echo "You did not guess the number." fi exit 0
#!/bin/bash # # guess.sh - guess the number the computer has chosen (1 try) # now with an elif # value=`bc -q <<< "(${RANDOM} % 10) + 1"` echo -n "Pick a value (1-10): " read num if [ "${num}" -eq "${value}" ]; then echo "You guessed correctly!" elif [ "${num}" -lt "${value}" ]; then echo "Too low" else echo "Too high" fi exit 0
#!/bin/bash # # guess.sh - guess the number the computer has chosen (1 try) # now with a for loop # value=`bc -q <<< "(${RANDOM} % 10) + 1"` for ((i=1; i<=6; i++)); do echo -n "[Guess ${i}/6] Pick a value (1-10): " read num if [ "${num}" -eq "${value}" ]; then echo "You guessed correctly!" break elif [ "${num}" -lt "${value}" ]; then echo "Too low" else echo "Too high" fi done if [ "${i}" -eq 7 ]; then echo "Too bad, my pick was ${value}" fi exit 0
#!/bin/bash # # guess.sh - guess the number the computer has chosen (1 try) # now with a while loop # ## ## Collect required information from the user ## echo -n "Please enter the lower range for the computer's choice: " read lower echo -n "Please enter the upper range for the computer's choice: " read upper # Make sure we have correct relationships for our range if [ "${lower}" -ge "${upper}" ]; then echo "Range values non-conformant" exit 1 fi echo -n "How many tries do you wish to have? (1-100): " read tries # Make sure we have a correct choice if [ ! "${tries}" -gt 0 ] || [ ! "${tries}" -le 100 ]; then echo "Invalid range, MUST be somewhere 1 through 100." exit 1 fi ## ## Computer's pick ## # Adjust upper variable with respect to lower variable for appropriate range let highval=${upper}-lower value=`bc -q <<< "(${RANDOM} % ${highval}) + ${lower}"` ## ## Main program ## i=1 while [ "${i}" -le "${tries}" ]; do echo -n "[Guess ${i}/${tries}] Pick a value (${lower}-${upper}): " read num if [ "${num}" -eq "${value}" ]; then echo "You guessed correctly!" i=0 break elif [ "${num}" -lt "${value}" ]; then echo "Too low" else echo "Too high" fi let i=${i}+1 done ## ## Check to see if we are out of luck/game over ## if [ "${i}" -gt 0 ]; then echo "Too bad, my pick was ${value}" fi exit 0
Rounds three and four could each have been done with a for loop OR a while loop. When a while is used, if we need to maintain a count, we need to do it ourselves, whereas with the for loop, it takes care of it as part of the loop.
The choice of loop to use is dependent upon your choosing; there really isn't a functional difference between them, although as indicated the resulting algorithm may need to be tweaked one way or the other to accommodate the desired intent of the script.
#!/bin/bash # # guess.sh - guess the number the computer has chosen (1 try) # now with functions # function determine { if [ "${num}" -eq "${value}" ]; then echo "You guessed correctly!" i=0 break elif [ "${num}" -lt "${value}" ]; then echo "Too low" else echo "Too high" fi } function init { ## ## Collect required information from the user ## echo -n "Please enter the lower range for the computer's choice: " read lower echo -n "Please enter the upper range for the computer's choice: " read upper # Make sure we have correct relationships for our range if [ "${lower}" -ge "${upper}" ]; then echo "Range values non-conformant" exit 1 fi echo -n "How many tries do you wish to have? (1-100): " read tries # Make sure we have a correct choice if [ ! "${tries}" -gt 0 ] || [ ! "${tries}" -le 100 ]; then echo "Invalid range, MUST be somewhere 1 through 100." exit 1 fi } function pick { ## ## Computer's pick ## # Adjust upper variable with respect to lower variable for appropriate range let highval=${upper}-lower value=`bc -q <<< "(${RANDOM} % ${highval}) + ${lower}"` } ## ## Main program ## init pick i=1 while [ "${i}" -le "${tries}" ]; do echo -n "[Guess ${i}/${tries}] Pick a value (${lower}-${upper}): " read num determine let i=${i}+1 done ## ## Check to see if we are out of luck/game over ## if [ "${i}" -gt 0 ]; then echo "Too bad, my pick was ${value}" fi exit 0
For those familiar with function in other languages, notice how we are just blatantly using variables, regardless of location. It would appear that bash prefers global scope for its variables (something to keep in mind).
#!/bin/bash # # guess.sh - guess the number the computer has chosen (1 try) # now with command-line arguments and function parameters # function determine { you="${1}" computer="${2}" if [ "${you}" -eq "${computer}" ]; then echo "You guessed correctly!" i=0 break elif [ "${you}" -lt "${computer}" ]; then echo "Too low" else echo "Too high" fi } function init { ## ## Collect required information from the user ## if [ "$#" -ge 1 ]; then lower="${1}" else echo -n "Please enter the lower range for the computer's choice: " read lower fi if [ "$#" -ge 2 ]; then upper="${2}" else echo -n "Please enter the upper range for the computer's choice: " read upper fi # Make sure we have correct relationships for our range if [ "${lower}" -ge "${upper}" ]; then echo "Range values non-conformant" exit 1 fi if [ "$#" -eq 3 ]; then tries="${3}" else echo -n "How many tries do you wish to have? (1-100): " read tries fi # Make sure we have a correct choice if [ ! "${tries}" -gt 0 ] || [ ! "${tries}" -le 100 ]; then echo "Invalid range, MUST be somewhere 1 through 100." exit 1 fi } function pick { ## ## Computer's pick ## lo="${1}" hi="${2}" # Adjust upper variable with respect to lower variable for appropriate range let highval=${hi}-${lo} value=`bc -q <<< "(${RANDOM} % ${highval}) + ${lo}"` } ## ## Main program ## init ${1} ${2} ${3} pick ${lower} ${higher} i=1 while [ "${i}" -le "${tries}" ]; do echo -n "[Guess ${i}/${tries}] Pick a value (${lower}-${upper}): " read num determine ${num} ${value} let i=${i}+1 done ## ## Check to see if we are out of luck/game over ## if [ "${i}" -gt 0 ]; then echo "Too bad, my pick was ${value}" fi exit 0
Here we make use of command-line arguments (the $1, $2, $3, …, $n; and $# variables), to specify potential values for upper, lower, and tries from the command-line, as follows:
lab46:~$ ./guess.sh 1 10 3 [Guess 1/3] Pick a value (1-10):
Where if we had left them out:
lab46:~$ ./guess.sh Please enter the lower range for the computer's choice:
We're also pretending some of the variables aren't global scope (function parameters are also $1, $2, $3, etc. just set to whatever values were passed to them).