In the last post we talked a little about what Bash is and ended with a simple "Hello World" example. In this post we are going to keep adding to our script by adding a variable and exploring two options for handling console output.

Console Output

In the previous post we used echo to output a message to the console. A second option, which is a bit more flexible, is printf. printf supports a few additional features, like string formatting, that make it a better default choice for your output needs. Here is the script again with printf:

#!/bin/bash
set -e
set -u

printf "Hello World\n"

One thing you might notice is the \n or "newline". Unlike echo, printf does not automatically insert a newline at the end of the line, it has to be added manually. I personally see this as a feature, as you get more control over the output of your text. This might not seem to be a good reason to use printf, and it isn't very exciting I know, but once we get into variables we can start to take advantage of more advanced features of printf.

Variables

If you have experience with PowerShell, some properties of Bash variables will feel familiar. In Bash, variables are denoted with a $ just like in PowerShell, but unlike PowerShell the $ is only needed when they are being referenced. When you are assigning a value to a variable, the $ is left off:

#!/bin/bash
set -e
set -u

my_var="World"

printf "Hello ${my_var}\n"

Above we assigned a value to my_var without using the $, but when we then referenced it in the printf statement, we had to use a $. We also enclosed the variable name in curly braces. This is not required in all cases, but it is a good idea to get in the habit of using them. In cases where you are using positional parameters above 9 (we'll talk about this later) or you are using a variable in the middle of a string the braces are required, but there is no harm in adding them every time you use a variable in a string. Here is a quick example to illustrate:

# Braces required since there is no whitespace to the right of the variable
printf "mybig${myvar}string"

# Braces not required, there is whitespace to the right of the variable
printf "mybig$myvar string"

As I said, there is no harm in always using braces. It is not required in some cases, but it almost always makes your code more readable.

Format String

As mentioned above, printf has some more advanced features you can use when dealing with variables. While variable expansion is cool, you can also do the following with printf:

#!/bin/bash
set -e
set -u

my_var="World"

printf "Hello %s\n" $my_var

This is a formatted string. In the example %s is replaced with the contents of the $my_var variable. String formatting is very powerful, in this example we are substituting a value into a string, but you can also do things like padding a string on the left or right, formatting a phone number, or controlling the precision of a floating point number. The ins and outs of formatting strings are best explained by the documentation.

One interesting thing I will note here though is the special character \a. This allows you to "print" an audible alert. This can be useful if you want to get the users attention during a script execution. Give it a try your self, go to a Bash command prompt and type: printf "\a".

Strings

This is a good time to go into strings a little deeper. Strings in Bash will be familiar for those with PowerShell experience. So far we have been enclosing our strings with double quotes, but you can also use single quotes. Like PowerShell, if you are trying to use variables directly in your strings ("Hello ${my_var}") you will need to use double quotes. If you are using the format capabilities of printf you can use either. To illustrate, here is a script you can try:

#!/bin/bash
set -e
set -u

my_var="World"

# printf with single quotes. Variable expansion doesn't happen
printf 'Hello ${my_var}\n' # Outputs 'Hello ${my_var}'
# printf with double quotes and variable expansion
printf "Hello ${my_var}\n" # Outputs 'Hello World'
# printf with single quotes and a format string
printf 'Hello %s\n' $my_var # Outputs 'Hello World'
# printf with double quotes and a format string
printf "Hello %s\n" $my_var # Outputs 'Hello World'

In cases where you need to include quotes within your strings, you have a few options:

Here are a few examples to illustrate:

#!/bin/bash
set -e
set -u

my_var="World"

# Double quotes nested in single quotes
printf 'Hello "World"\n'
# Single quotes nested in double quotes
printf "Hello 'World'\n"
# Escaped double quotes nested in double quotes
printf "Hello \"World\"\n"
# Escaped double quotes nested in doulbe quotes with variable expansion
printf "Hello \"${my_var}\"\n"

Color!

Now that we know how to print text to a console, and we know how to use variables, lets add a little pizzazz to our Hello World script:

#!/bin/bash
set -e
set -u

# Colors
red="`tput setaf 1`"
end="`tput sgr0`"

printf "${red}Hello${end} World\n"

Variables can be used for a lot of things, in this case we are storing some ANSI escape codes and using them to color our output. The codes are being generated by a small app called tput, you can read about using it (including a handy color table) here. This can be useful when you are trying to make console output more clear, like making errors red for example.

Final Thoughts

User feedback is an important part of any script and you have a lot of options with Bash. There is even more to know about console output, but we are going to hold off on that until a later post when we cover error handling. Until then stay tuned for the next post in this series where we will discuss arithmetic operations, conditional logic, and looping.