Colorful

In the next example, we'll create a script that allows us to print text to our terminals in a few different colors. It does this based on a function that has two parameters: string and color. Take a look at the following commands:

reader@ubuntu:~/scripts/chapter_13$ vim colorful.sh 
reader@ubuntu:~/scripts/chapter_13$ cat colorful.sh
#!/bin/bash

#####################################
# Author: Sebastiaan Tammer
# Version: v1.0.0
# Date: 2018-11-17
# Description: Some printed text, now with colors!
# Usage: ./colorful.sh
#####################################

print_colored() {
# Check if the function was called with the correct arguments.
if [[ $# -ne 2 ]]; then
echo "print_colored needs two arguments, exiting."
exit 1
fi

# Grab both arguments.
local string=$1
local color=$2

# Use a case-statement to determine the color code.
case ${color} in
red)
local color_code="e[31m";;
blue)
local color_code="e[34m";;
green)
local color_code="e[32m";;
*)
local color_code="e[39m";; # Wrong color, use default.
esac

# Perform the echo, and reset color to default with [39m.
echo -e ${color_code}${string}"e[39m"
}

# Print the text in different colors.
print_colored "Hello world!" "red"
print_colored "Hello world!" "blue"
print_colored "Hello world!" "green"
print_colored "Hello world!" "magenta"

A lot is happening in this script. To help with your understanding, we'll go through it piece by piece, starting with the first part of the function definition:

print_colored() {
# Check if the function was called with the correct arguments.
if [[ $# -ne 2 ]]; then
echo "print_colored needs two arguments, exiting."
exit 1
fi

# Grab both arguments.
local string=$1
local color=$2

The first thing we do within the function body is check the number of arguments. The syntax is the same as the checks we normally do for arguments passed to the entire script, which might be helpful or perhaps confusing. A good thing to realize is that the $# construct applies to the scope in which it is used; if it is used within the main script, it checks the arguments passed there. If it is used, like it is here, within a function, it checks the number of arguments passed to the function. The same goes for $1, $2, and so on: if used within a function, they refer to the ordered arguments passed to the function, and not the script in general. When we grab the arguments, we write them to local variables; we don't strictly need to do that in this simple script, but it is always good practice to mark variableses local when you only use them in the local scope. You might imagine that in larger, more complex scripts many functions use variables that might accidentally be called the same thing (in this case, string is a very common word). By marking them local, you're not only improving readability, but also preventing errors caused by variables that have the same name; all in all, a very good idea. Let's get back to the next part of our script, the case-statement:

  # Use a case-statement to determine the color code.
case ${color} in
red)
color_code="e[31m";;
blue)
color_code="e[34m";;
green)
color_code="e[32m";;
*)
color_code="e[39m";; # Wrong color, use default.
esac

Now is an excellent time to introduce case. A case-statement is basically a very long if-then-elif-then-elif-then... chain. The more options there are for a variable, the longer the chain would become. With case, you can just say for certain values in ${variable}, do <something>. In our example, that means that if the ${color} variable is red, we'll set another color_code variable to e[31m (more on that in a bit). If it is blue, we'll do something else, and the same goes for green. Finally, we'll define a wildcard; any value for the variable that was not specified will go through there, as a sort of catch-all construction. If the color specified is something incompatible, such as dog, we'll just set the default color. The alternative would be breaking off the script, which is a bit of an overreaction to a wrong color. To terminate a case, you'll use the esac keyword (which is the reverse of case), in a similar manner to if, which is terminated by its reverse, fi.

Now, on to the technical aspect of colors on your terminal. While most things we've been learning about are Bash or Linux specific, printed colors are actually defined by your terminal emulator. The color codes we're using are pretty standard and should be interpreted by your terminal as do not print this character literally, but instead change the color to <color>. The terminal sees an escape sequence, e, followed by a color code, [31m, and knows you're instructing it to print a different color than previously defined (often defaults for that terminal emulator, unless you've changed the color scheme yourself). You can do many more things (as long as your terminal emulator supports this, of course) with escape sequences, such as creating bold text, blinking text, and another background color for your text. For now, remember the e[31m sequence is not printed but interpreted. For the catch-all in case, you do not want to explicitly set a color, but instead signal the terminal to print in the default color. This means that for every compatible terminal emulator, the text is printed in the color the user has chosen (or got assigned by default).

Now for the final part of the script:

  # Perform the echo, and reset color to default with [39m.
echo -e ${color_code}${string}"e[39m"
}

# Print the text in different colors.
print_colored "Hello world!" "red"
print_colored "Hello world!" "blue"
print_colored "Hello world!" "green"
print_colored "Hello world!" "magenta"

The last part of the print_colored function actually prints the colored text. It does this by using the good old echo with the -e flag. man echo reveals that -e enables interpretation of backslash escapes. If you do not specify this option, your output will just be something like e[31mHello world!e[39m. A good thing to know in this situation is that as soon as your terminal encounters a color code escape sequence, all subsequent text will be printed in that color! Because of this, we end the echo with "e[39m", which resets the color for all following text back to default.

Finally, we call the function multiple times, with the same first argument, but a different second argument (the color). If you run the script, the output should look similar to this:

In the preceding screenshot, my color scheme is set to green-on-black, which is why the last Hello world! is bright green. You can see it is the same color as bash colorful.sh, which should be all the confirmation you need to be sure the [39m color code is actually default.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.150.41