Is it sed or echo problem? What I'm doing wrong?

$> cat ~/bin/color_test.sh 

ColorOff='\e[0m'       # Text Reset
BWhite='\e[1;37m'      # Bold White

string="test TEST test"
echo -e "$string" | sed -e "s/TEST/${BWhite}TEST${ColorOff}/g"

$> ~/bin/color_test.sh 
test e[1;37mTESTe[0m test

TEST with bold highlighting is what was expected.


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:


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")
  • Btw, echo -e "${BWhite}AAAA${ColorOff}" shows `\AAAA`. It's a pity, because than I need to keep regular_color_constants and SED_color_constants. Actually, I want to have only regular_color_constants, and fix echo and sed options to get what I want. – ДМИТРИЙ МАЛИКОВ Aug 23 '11 at 14:02
  • That solution is rather fragile (what if $string contains a backslash?) and is quite a bit more complicated than necessary. To understand quoting, take things one at a time. E.g. the three backslashes aren't sed magic at all: first there are double quotes, and "\\\e" is the two-character string \e; then sed understands \e as “the character e literally”. – Gilles Aug 23 '11 at 22:25

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.