Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash Script printf colors from variable?

Tags:

c

bash

shell

I was hoping to see if someone can point out what I am doing wrong because I am stumped. I am trying to learn bash scripting to deploy a dev test server. One of the things I am trying to achieve is outputting status outputs when a part of the script completes or an action completes. As an example:

    printf "[ %s ] %s distribution detected. Validated as supported by this script.\n" "$PASSED" "$LINUX_DISTRO"

The problem I am having is formatting the value of the first string, %s, which is $PASSED. In the beginning of the script I have defined $PASSED as

PASSED="\e[32mPASSED\e[0m"

However, when I go to execute the script, the output looks like the following:

[ \e[32mPASSED\e[0m ] CENTOS distribution detected. Validated as supported by this script.

Instead of the correct output which looks like:

[ PASSED ] CENTOS distribution detected. Validated as supported by this script.

Where "PASSED" is written in green coloring.

However, I did notice that if I do the following:

printf "[ $PASSED ] %s distribution detected. Validated as supported by this script.\n" "$LINUX_DISTRO"

The above behaves correctly, but I believe isn't the correct way of doing it. Any ideas?

like image 236
Alex Mikhaelson Avatar asked Mar 02 '16 16:03

Alex Mikhaelson


2 Answers

You want bash to interpret the backslash characters. Use %b instead of %s in your printf. So instead you should have the following.

printf "[ %b ] %s distribution detected. Validated as supported by this script.\n" $PASSED $LINUX_DISTRO

Also, I modified your variable.

PASSED="\e[00;32mPASSED\e[0m"
like image 106
barefly Avatar answered Oct 19 '22 22:10

barefly


Another (non-standard) solution is to put the escape character directly in the original string, rather than \e for printf to interpret.

PASSED=$'\e[32mPASSED\e[0m'
printf '[ %s ] some test\n' "$PASSED"

However, this assumes that your script is run by /bin/bash, not /bin/sh (which might be bash, but run in POSIX-compliant mode).

Using %b has the same problem: it is specific to bash, and you may not want to assume that bash is the shell executing your script.

A fully POSIX-compliant solution is to use printf itself to create the value of PASSED.

# \e not supported by POSIX; use \033 (octal) instead.
PASSED=$(printf '\033[32mPASSED\033[0m')
printf '[ %s ] some test\n' "$PASSED"
like image 1
chepner Avatar answered Oct 19 '22 23:10

chepner