Introduction to Bash Scripting: Display User Messages and Catch User Input

By:   |   Updated: 2018-12-05   |   Comments (2)   |   Related: > SQL Server on Linux


Problem

You are a SQL Server Database Administrator and you are starting to use SQL Server on Linux. As you have probably found out, there are several administrative tasks that you need to do differently on Linux versus Windows. In this tip I will show you the different ways you can use Bash scripting to display messages and also how to catch user input.

Solution

When you want to build a Bash script (or any other kind of script) the first thing you need to know is how the script is going to be used. Without too much thinking we can define two categories of scripts: those that run in the background like Cron jobs and those that require user input, like an installation script.

If your goal is to create a script that runs in the background, you can't catch any user input and must rely on getting everything for your script to work from a configuration file. We will see how to read from files in another tip. Also, you should probably re-think about writing to the console for these background scripts and consider writing to a text file for logging instead.

If your goal is to write an interactive script that can be able to display information and receive user input, then I will show how this can be done in this tip.

Working with Interactive Bash Scripts

When we aim to give some informative message to the console, Bash gives us two tools we can take advantage of. If you have been reading the tips in this series you already know one, which is the echo command. The other one is the printf function. If you ever worked with C or C++ languages you will find this easy. But if you haven't, after reading this tip you will see it is easy to do.

The Bash echo Command

If you have been reading my previous tips in this series you already saw how to use the echo command to display basic output to the console. But this command allows more complex usage depending on which parameter you pass to it.

In the next table I have copied the parameters available from the echo command page.

Parameter Description
-n Don't write the trailing newline.
-e Enable interpretation of backslash escapes. This is the most important and the one I will get covered.
-E Disable interpretation of backslash escapes which is the default behavior.

Let's consider the following script:

#!/bin/bash

Variable1="Hello"
Variable2="World"
echo $Variable1
echo $Variable2

echo -n $Variable1
echo -n $Variable2

On the next screen capture you will see the output of that script execution. Notice that the addition of the –n parameter suppressed the new line.

Using the -n parameter with echo command.

The –e parameter of the echo command allows us with the possibility to change the way we write our messages to the console by using escape sequences. In the next table I wrote a list of each escape sequence and its meaning. All the ASCII codes are expressed in decimal notation.

Escape Sequence Description
\a Writes the ASCII 07 character to the console which is known as Alert or Bell. Basically, it plays an alert sound on your speaker.
\b Writes one backspace character (ASCII 08) to the console. The result is like pressing the backspace key in your keyboard. It deletes the character before it.
\c It produces no further output. Use this when you want to hide the output of what is after the \c.
\e Writes the escape character (ASCII 27) to the console. It's like pressing the escape key in your keyboard.
\f Writes the form feed character (ASCII 12) to the console
\n Starts writing in a new line
\r Performs a carriage return.
\t Writes a Horizontal tab (like pressing the tab key).
\v Writes a Vertical tab.
\\ Writes a backslash.
\0NNN The eight-bit character whose value is the octal value NNN (zero to three octal digits)
\xHH The eight-bit character whose value is the hexadecimal value (one or two hexadecimal digits).

Echo Examples

Now I will give you a few examples using an escape sequence.

In the next script I show you how the \c escape sequence suppresses the output of the text that follows and additionally how to write a vertical tab with the \v escape sequence.

#!/bin/bash

echo -e "Hello \c World!"
echo
echo 
echo -e "Hello\v World!"
Using escape characters with the echo command.

In the next example, I will show you how to write characters by using hexadecimal and octal notation.  You can use the following link to get an ASCII table in decimal, hexadecimal and octal numeric systems: http://www.asciitable.com/.

#!/bin/bash

#H 48 110
#e 65 145
#l 6C 154
#l 6C 154
#o 6F 157
echo -e "\x48\x65\x6C\x6C\x6F World!" 
echo -e "\0110\0145\0154\0154\0157 World!"
Writting the classic "Hello World!" message with escape characters in Hexadecimal and Octal numbers.

The Bash printf Command

This command is an improved version of echo, because it provides a method for printing formatted text like the C/C++ printf function does.

The syntax of this command is as follows:

printf [FORMAT] [ARGUMENT_1] …[ARGUMENT_n]

Basically FORMAT contains the static text and variables or constants you want to print to screen formatted with any of the available format codes and modifiers. In case you want to write variables or constants you should not include them in the format section. Instead you have to specify the format which you want to be used to print each of those. After setting the format you have to include as arguments the variables or constants you like to print in the same order you specified their format. As a side note, notice that both format and arguments are not separated by commas.

Format Description
%b Print the associated argument while interpreting backslash escapes in there
%q Print the associated argument shell-quoted, reusable as input
%d Print the associated argument as signed decimal number
%i Same as %d
%o Print the associated argument as unsigned octal number
%u Print the associated argument as unsigned decimal number
%x Print the associated argument as unsigned hexadecimal number with lower-case hex-digits (a-f)
%X Same as %x, but with upper-case hex-digits (A-F)
%f Interpret and print the associated argument as floating point number
%e Interpret the associated argument as a number in double precision, and print it in exponential (<N>±e<N>) format
%E Same as %e, but with an upper-case E in the printed format
%g Interprets the associated argument as double, but prints it like %f or %e
%G Same as %g, but print it like %E
%c Interprets the associated argument as char: only the first character of a given argument is printed
%s Interprets the associated argument literally as string
%n Assigns the number of characters printed so far to the variable named in the corresponding argument. Can't specify an array index. If the given name is already an array, the value is assigned to the zero elements.
%a Interprets the associated argument as double, and prints it in the form of a C99 hexadecimal floating-point literal.
%A Same as %a, but print it like %E
%(FORMAT)T outputs the date-time string resulting from using FORMAT as a format string for strftime(3). The associated argument is the number of seconds since Epoch, or -1 (current time) or -2 (shell startup time). If no corresponding argument is supplies, the current time is used as default
%% No conversion is done. Produces a % (percent sign)

In the following script you can take a look at some examples on the usage of the format wildcard.

Printf Escape codes

Just like the echo command, printf also has escape codes. In order to maintain compatibility, printf keeps the same escape codes than the echo command, but adds a few more that I will enumerate next.

Escape Sequence Description
\'' Writes a " quote.
\? Writes a "?" sign.

Printf Examples

I will give a few examples showing the usage of printf.

Take a look at the next script when I show you how to format numbers. Notice that I use \n to start the next line in a new line.

#!/bin/bash
MyVar=-112450000000000
printf "MyVar as signed decimal number: %d\n" $MyVar
printf "MyVar as floating point number: %f\n" $MyVar
printf "MyVar as double precision number: %e\n" $MyVar
printf "MyVar as double precision number: %E\n" $MyVar
printf "MyVar as double precision number: %g\n" $MyVar
printf "MyVar as double precision number: %G\n" $MyVar
printf "MyVar as unsigned decimal number: %u\n" $MyVar
printf "MyVar as C99 hexadecimal floating-point number: %u\n" $MyVar
printf "MyVar as a character: %c\n" $MyVar
printf "MyVar as a string: %s\n" $MyVar
printf "Here is a percentage sign: %%\n"

On the next image you can see the execution of the previous script.

Using printf to format numbers and strings.

When to use printf instead of echo?

Printf is ideal when you need to display formatted text or a statement composed with many variables.

Using the Read Command to Catch User Input

In order to write an interactive script, the scripting language must give you the possibility to grab user input. Bash is not an exception. It provides us with the read command. This command reads one line from the console (the standard input) or any file descriptor you pass as a parameter. I will cover file descriptors in another tip, but for now think that everything in Linux is a file. Yes, even the console as file which is /dev/tty. As homework, try to write something to that file for example by running the following command.

ls > /dev/tty

The read command has the following syntax.

read [options] VAR1 VAR2 ... VARN

The options are described in the table below. VAR1 … VARN are the destination variables for each word separated by a space character of the line. In case you only use one variable, it will get all the words.

Option Description
-a ArrayName Each input word is assigned to an item of a given array.
-d DELIM The first character of DELIM will be used as the end of the line instead of CRLF.
-e The GNU Readline command (https://en.wikipedia.org/wiki/GNU_Readline) is used to catch the line.
-n NCHARS NCHARS means the number of characters you want to read from the input. For example, if NCHARS is two, after you press two keys on your keyboard the read command will end and grab only those two characters.
-p PROMPT Shows the content of PROMPT (which usually is a string) before reading the input message. You can use this in case you want to print a message like "enter your folder:" and then grab the input.
-r Makes the backslash character (\) to not act as an escape character.
-s When this option is used the user input is not show to the screen. This is ideal if you want to retrieve a password.
-tTIMEOUT If the user didn't enter a value during the seconds defined in TIMEOUT, you will receive an error message.
-u FD Instead of reading the input from the console uses the file descriptor specified in FD.

Read Command Examples

The next script prompts the user for his name and saves it in a variable.

#!/bin/bash
read -p "Enter your Name:" Name
echo "Your name is " $Name

On the next screen capture you will see the execution of the previous script.

Catching user input with read command.

In the next example I use the –d option to change the end of line character to ";" instead of the default CRLF.

#!/bin/bash

echo "Enter the following personal info. Finish with semicolon (;)"
echo "Name"
echo "Surname"
echo "Address"

read -d ";" Info
printf "\nYou entered:"
printf "%s\n" $Info 

The next screen capture shows the results of the execution of the previous script.

Using the -d option to change the end of line character.

As you may guess, this is not very useful. It would be awesome if we could parse each data element in an array. The good thing is that we can do that! Take a look at the following script.

#!/bin/bash

declare -a MyArray
echo "Enter the following personal info. Finish with semicolon (;)"
echo "Name"
echo "Surname"
echo "Phone"

read -a MyArray -d ";"
printf "\nYou entered:"
printf "%s\n%s\n%s\n" ${MyArray[0]} ${MyArray[1]} ${MyArray[2]}
Saving each input word as items in an array with the -a option.
Next Steps


sql server categories

sql server webinars

subscribe to mssqltips

sql server tutorials

sql server white papers

next tip



About the author
MSSQLTips author Daniel Farina Daniel Farina was born in Buenos Aires, Argentina. Self-educated, since childhood he showed a passion for learning.

This author pledges the content of this article is based on professional experience and not AI generated.

View all my tips


Article Last Updated: 2018-12-05

Comments For This Article




Wednesday, February 13, 2019 - 11:00:27 PM - Daniel Farina Back To Top (79032)

Hi Bruce!

Thank you so much for reading and asking! 

Yes, in the last two images both outputs of the execution of ./sample.sh are the same.... But both images are different :-)... 

Look at the top of both images and you will see that the output of "cat sample.sh" is different. The idea was showing both ways of parsing data in a bash script.

Thank you!!!


Wednesday, February 13, 2019 - 1:52:54 AM - BE Davis Brown Back To Top (79021)

Hello Daniel

Your article has helped me learn more about shell scripts, but I don't see any difference in your last example both output looks the same. On "https://www.mssqltips.com/sqlservertip/5772/introduction-to-bash-scripting-display-user-messages-and-catch-user-input/"

Thank You

Bruce















get free sql tips
agree to terms