We'll show one more check before we finish this chapter. Halfway through the book, in Chapter 9, Error Checking and Handling, we presented a script that dealt with a user that could supply either a 'yes' or a 'no'. But, as we explained there, the user might also use 'y' or 'n', and perhaps even a capital letter in there somewhere. By secretly using a little Bash expansion, which you will see properly explained in Chapter 16, Bash Parameter Substitution and Expansion, we were able to make a relatively clear check for user input. Let's get that thing in our library!
reader@ubuntu:~/scripts/chapter_13$ vim ~/bash-function-library.sh
reader@ubuntu:~/scripts/chapter_13$ cat ~/bash-function-library.sh
#!/bin/bash
#####################################
# Author: Sebastiaan Tammer
# Version: v1.3.0
# Date: 2018-11-17
# Description: Bash function library.
# Usage: source ~/bash-function-library.sh
#####################################
<SNIPPED>
# Checks if the user answered yes or no.
check_yes_no() {
# Input validation.
if [[ $# -ne 1 ]]; then
echo "Need exactly one argument, exiting."
exit 1 # No validation done, exit script.
fi
# Return 0 for yes, 1 for no, exit 2 for neither.
if [[ ${1,,} = 'y' || ${1,,} = 'yes' ]]; then
return 0
elif [[ ${1,,} = 'n' || ${1,,} = 'no' ]]; then
return 1
else
echo "Neither yes or no, exiting."
exit 2
fi
}
We've got a little advanced scripting cooked up for you with this example. Instead of a binary return, we now have four possible outcomes:
- Function incorrectly called: exit 1
- Function found a yes: return 0
- Function found a no: return 1
- Function found neither: exit 2
With our new library function, we'll take the yes-no-optimized.sh script and replace the complex logic with (almost) a single function call:
reader@ubuntu:~/scripts/chapter_13$ cp ../chapter_09/yes-no-optimized.sh library-yes-no.sh
reader@ubuntu:~/scripts/chapter_13$ vim library-yes-no.sh
reader@ubuntu:~/scripts/chapter_13$ cat library-yes-no.sh
#!/bin/bash
#####################################
# Author: Sebastiaan Tammer
# Version: v1.0.0
# Date: 2018-11-17
# Description: Doing yes-no questions from our library.
# Usage: ./library-yes-no.sh
#####################################
# Load our Bash function library.
source ~/bash-function-library.sh
read -p "Do you like this question? " reply_variable
check_yes_no ${reply_variable} &&
echo "Great, I worked really hard on it!" ||
echo "You did not? But I worked so hard on it!"
Take a minute to look at the preceding script. It will probably be a little confusing at first, but try to remember what && and || do. Because of some smart ordering we applied, we can use && and || in sequence to achieve our result. Look at it like this:
- If check_yes_no returns an exit status of 0 (when a yes is found), the command after && is executed. Since that echoes the success, and echo has an exit code of 0, the failure echo after the next || is not executed.
- If check_yes_no returns an exit status of 1 (when a no is found), the command after && is not executed. However, it continues until it reaches ||, which goes on to the failure echo since the return code was still not 0.
- If check_yes_no exits on either the lack of argument or lack of yes/no, the commands after both && and || are not executed (because the script is given an exit instead of return, so code execution is stopped immediately).
Pretty clever right? However, we must admit, it's a little against most things we've been teaching you with regards to readability. Consider this a teaching exercise for chaining && and || instead. If you'd want to implement the yes-no check yourself, it would probably be better to create dedicated check_yes() and check_no() functions. In any case, let's see if our tricked out script actually works as we hope it does:
reader@ubuntu:~/scripts/chapter_13$ bash library-yes-no.sh
Do you like this question? Yes
Great, I worked really hard on it!
reader@ubuntu:~/scripts/chapter_13$ bash library-yes-no.sh
Do you like this question? n
You did not? But I worked so hard on it!
reader@ubuntu:~/scripts/chapter_13$ bash library-yes-no.sh
Do you like this question? MAYBE
Neither yes or no, exiting.
reader@ubuntu:~/scripts/chapter_13$ bash library-yes-no.sh
Do you like this question?
Need exactly one argument, exiting.
All scenarios as we've defined them in the check work out. Great success!
We'd like to end this chapter with a small exercise for you. In this chapter, before we introduced the function library, we already created a few functions: two for error handling, one for colored printing, and one for reversing text. Your exercise is simple: grab those functions and add them to your personal function library. Make sure to keep the following things in mind:
- Are the functions verbose enough to be included in the library as is, or could they use more?
- Can we call the functions and deal with the output as is, or would an edit be preferable?
- Are returns and exits properly implemented, or do they need to be adjusted to work as a generic library function?
There are no right or wrong answers here, just things to consider. Good luck!