Colorizing Bash Output

When I developed this, a great majority of my professional development was in Perl.  Additionally, we have had a focus on building more robust unit test scripts for the code that is written.  Especially as the tests have started growing pretty large, I started looking for ways to make the test output a bit more readable.  Since these are built using existing perl packages like Test::More, I am somewhat limited in my customization choices.  When looking for possibilities, most of the answers that I found were code that you could add to your script to do the colorization.  Unless I wanted to build custom versions of the packages we use, that wasn’t the best option.

I also looked into multitail since I had used that for colorizing some log outputs, but it never seemed well suited for taking the output of a single-run script.  Not only is scrolling around a bit awkward, but it doesn’t tend to like to leave the output available after the run. Multitail does ok if you first redirect the output to a file, then multitail that file, but that is a bit more difficult to swing if you don’t want be switching between windows (plus it leaves a file that you’ll need to clean up at some point).

What I ended up going with was this script.  The nice thing about it is that it could be pretty easily tailored for whatever script for which you wanted to colorize the output. As it is currently written, it makes the output of Perl’s Test::More .t files a lot clearer and nicer to look at!

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#!/bin/bash

# For reference, a list of available color choices
# Black        0;30     Dark Gray     1;30
# Red          0;31     Light Red     1;31
# Green        0;32     Light Green   1;32
# Brown/Orange 0;33     Yellow        1;33
# Blue         0;34     Light Blue    1;34
# Purple       0;35     Light Purple  1;35
# Cyan         0;36     Light Cyan    1;36
# Light Gray   0;37     White         1;37

# color definitions
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
WHITE='\033[1;37m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

# Reset the colors if killed
trap 'printf "${NC}"' SIGINT SIGTERM

# Set up regexes so indentation is irrelevant
space_regex='^[[:space:]]*#';
not_ok_regex='^[[:space:]]*not ok';
ok_regex='^[[:space:]]*ok';

while IFS= read -r line
do
    # Comments
    if [[ $line =~ $space_regex ]]
        then
            printf "${YELLOW}$line\n"
    # Failed tests
    elif [[ $line =~ $not_ok_regex ]]
        then            
            printf "${RED}$line\n"
    # Passed tests
    elif [[ $line =~ $ok_regex ]]
        then            
            printf "${GREEN}$line\n"
    # Default color
    else 
        printf "${WHITE}$line\n"
    fi        
done < "${1:-/dev/stdin}"

# ensure colors are set back to normal
printf "${NC}"

To use it, I run something like perl test.t 2>&1 | ./colorize.sh which results in output like this.

I’m sure that I could do some more customization, but I was pretty happy with how it turned out. It colorizes the different statements that we tend to have, and catches kill signals so your colors will reset to normal if you kill the run before it finishes. If I do make any updates, I’ll add them to the snippet.