5

How do I store colored text in a variable and print it with color later?

I never see the answer to this question in 100 searches it's all about PS1 prompts, or inline printf's or using data from ls --color. I need to add the color to the variable myself AND have it print colorized later.

name="Hello"
name=$name"\e[36m\(Test\)\e[0m"
echo $name
printf $name

the ouptut i get from this is:

Hello \e[36m(Test)\e0m

It doesn't colorize from the data in the variable.
how do we STORE the color code in a variable for printing later
Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner

  • \e is a special escape code specifically for echo -e which is parsed into an Escape character,^[ (literally, Ctrl-[; not caret [). To store that into a variable without learning type a literal Escape in your editor, you can use (for example), BOLD="$(echo -e "\e[1m")" followed by echo $BOLD. – DopeGhoti Dec 14 '15 at 22:03
  • Bash's echo will not interpret \e unless called as echo -e, but printf should. Does neither of your calls result in color printing? – dhag Dec 14 '15 at 22:04
  • Nowadays I save the escape codes as snippets in my text editor instead of using variables. the reason is I always end up wanting to use the escape codes in scripts where the variables weren't initialised - so if you just put the raw escape code into the script - you dont need the variables to be available - but you do lose the human readable variable name – the_velour_fog Dec 15 '15 at 9:27
  • Yes. In the direct code above, when I run that script i get the same output regardless of echo or printf. In the long run for what I was trying to do, I solved it a different way, but the answers on this thread are rather educational. – JaedenRuiner Dec 15 '15 at 15:14
3

In bash there are three options: echo -e, printf, and $'...'.

The last one is the easiest:

$ name="Hello"; name=$name$'\033[34m(Test)\e[0m' ; echo "$name"
Hello(Test)

In this case the color code was stored in the variable. The easiest way to "see" the codes (apart from seeing the color) is to use some hex viewer:

$ echo "$name" | od -vAn -tcx1
   H   e   l   l   o 033   [   3   5   m   (   T   e   s   t   )
  48  65  6c  6c  6f  1b  5b  33  35  6d  28  54  65  73  74  29
 033   [   0   m  \n
  1b  5b  30  6d  0a

Use it when you need to "see" the codes (and why they do or don't work).

The color codes are inside the var, already interpreted. In that way you could create a var for some color, and use it:

$ blue=$'\033[34m'; reset=$'\033[0m'
$ echo "Hello $blue Test $reset Colors"

The other way is to store the codes inside a variable, and interpret them each time their "effect" is needed.

$ blue='\033[34m'; reset='\033[0m'
$ echo "Hello $blue Test $reset Colors"
Hello \033[34m Test \033[0m Colors
$ echo -e "Hello $blue Test $reset Colors"
Hello  Test  Colors

With "Test" in Blue, and "Colors" in Black (if your console screen is white).

The command echo -e is not as portable (and safe) as printf:

$ blue='\033[34m'; reset='\033[0m'
$ printf "%s $blue%s $reset%s" "Hello" "Test" "Colors"
Hello Test Colors

The whole list of colors (background) will be visible with (printing an space):

 printf '\e[%sm ' {40..47} 0; echo

Or, with foreground colors:

 printf '\e[%smColor=%s  ' {30..37}{,} 0 0; echo
|improve this answer|||||
2

Rather than

name="Hello"
name=$name"\e[36m\(Test\)\e[0m"
echo $name
printf $name

you could make it a little simpler to follow with

name="Hello"
name=$name"$(tput setaf 6)(Test)$(tput sgr0)"
echo $name
printf $name

That approach would make it simpler than remembering the appropriate strings for extended colors (beyond 8). For instance, running this script:

#!/bin/sh
[ $# = 0 ] && exec $0 6
name="Hello"
name=$name"$(tput setaf $1)(Test)$(tput sgr0)"
echo $name
printf $name

with parameter 6, 12, 24 and TERM set to xterm-256color, the corresponding $name with \E as escape would be

Hello\E[36m(Test)\E(B\E[m
Hello\E[94m(Test)\E(B\E[m
Hello\E[38;5;24m(Test)\E(B\E[m

For reference:

|improve this answer|||||
1

\e is a special escape code specifically for echo -e which is parsed into an Escape character,^[ (literally, Ctrl-[; not caret [). To store that into a variable without learning type a literal Escape in your editor, you can use:

#!/bin/bash
BOLD="$( echo -e "\e[1m" )"
CYAN="$( echo -e "\e[36m" )"

echo "I am feeling ${BOLD}really ${CYAN}blue!"
|improve this answer|||||
0

You can use the ANSI C quoting to have the special characters translated: $'...'. So that is a dollar before the single quotes. This allows one to type \n and \t for newline and tab, but also for color codes.

name="Hello"
name=$name$'\e[36m\(Test\)\e[0m'
echo $name
printf $name

These ANSI C escapes were introduced KSH more recent than the 88 version, and are available on bash, zsh and busybox sh. It is not available on dash.

|improve this answer|||||
0

printf should display the colors correctly

[user@host ~]$ name="Hello"
[user@host ~]$ name=$name"\e[36m\(Test\)\e[0m"
[user@host ~]$ echo $name
Hello\e[36m\(Test\)\e[0m
[user@host ~]$ printf $name
Hello\(Test\)[user@host ~]$

In the last line "Test" is cyan and there is no new line.


for echo you need to add -e:

$ help echo
[...]
Options:
      -n        do not append a newline
      -e        enable interpretation of the following backslash escapes
      -E        explicitly suppress interpretation of backslash escapes
[...]

You can store colors in variables as long as you use echo -e.

export txtblk='\033[0;30m' # Black - Regular
export txtred='\033[0;31m' # Red
export txtgrn='\033[0;32m' # Green
export txtylw='\033[0;33m' # Yellow
export txtblu='\033[0;34m' # Blue
export txtpur='\033[0;35m' # Purple
export txtcyn='\033[0;36m' # Cyan
export txtwht='\033[0;37m' # White
export bldblk='\033[1;30m' # Black - Bold
export bldred='\033[1;31m' # Red
export bldgrn='\033[1;32m' # Green
[...]
export undblk='\033[4;30m' # Black - Underline
export undred='\033[4;31m' # Red
[...]
export bakblk='\033[40m'   # Black - Background
export bakred='\033[41m'   # Red
export badgrn='\033[42m'   # Green
export txtrst='\033[0m'    # Text Reset

[user@host ~]$ echo "$txtblu hello"
\033[0;34m hello
[user@host ~]$ echo -e "$txtblu hello"
hello # this text is blue
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.