Bash color output fails
sed
doesn't treat \e
as an escape sequence. With GNU sed, and most other sed implementations out there, \e
in an s
replacement text just means e
. The only backslash escapes you can use portably in s
replacement text are \\
to mean a backslash, \&
to mean a literal &
, \/
(where /
is the delimiter character) for a literal /
, and \1
through \9
for backreferences. GNU sed and BusyBox (but not e.g. OpenBSD sed) adds \n
for a newline. Thus the output of your sed command has a literal e
.
In bash, you can easily put a literal escape character in your variables from the start. \e
is one of the escape sequences recognized by the $'…'
construct.
ColorOff=$'\e[0m' # Text Reset
BWhite=$'\e[1;37m' # Bold White
There are two problems in your echo
command.
I expanded the variables for brevity.
$ echo -e "test TEST test" | sed -e "s/TEST/\e[1;37mTEST\e[0m/g"
test e[1;37mTESTe[0m test
First problem: the backslashes are lost somewhere between sed magic and shell magic. You have to escape them.
$ echo -e "test TEST test" | sed -e "s/TEST/\\e[1;37mTEST\\e[0m/g"
test e[1;37mTESTe[0m test
Still doesn't work. Maybe more escaping?
$ echo -e "test TEST test" | sed -e "s/TEST/\\\e[1;37mTEST\\\e[0m/g"
test \e[1;37mTEST\e[0m test
Finaly the backslashes are coming through. I have no idea why we need three backslashes, that is some weird sed magic.
Second problem: the echo -e
is pointless. -e
enables interpretation of backslash escapes, but all echo -e
gets to interpret is "test TEST test"
. The backslash escapes are coming from sed, which does not care about them and prints them raw.
What you want is this:
$ echo -e $(echo "test TEST test" | sed -e "s/TEST/\\\e[1;37mTEST\\\e[0m/g")
test TEST test
with bold TEST in output.
Here is the full script with the changes:
#!/bin/bash
ColorOff='\\\e[0m' # Text Reset
BWhite='\\\e[1;37m' # Bold White
string="test TEST test"
echo -e $(echo "$string" | sed -e "s/TEST/${BWhite}TEST${ColorOff}/g")