0

I have multiple Bash variables for ANSI terminal colors. One is ANSI_NOCOLOR and defined as this:

ANSI_NOCOLOR="\e[0m"

When I use it togather with a backslash character \ (escaped as \\ in Bash strings), I get an unexpected output.

Example:

echo -e "command --with --many --options \\$ANSI_NOCOLOR"
echo -e "--more --options"

This results in:

command --with --many --options \e[0m
--more --options

This example can be reduced to:

$ echo -e "\\\e[0m"
\e[0m

Why is a tripple backslash in Bash not acting as normally known from other C-like languages?

Expected / C-like behavior:

Escape sequences are left-associative. Thus,

  1. the first two \\ are printed as \,
  2. the remaining \ is doing a look-ahead(1) to find e for creating the ESC character.

Workaround:
After some planing with backslashes, I found, that 5 !! backslashes are required. I still would like to read an explanation, why it behaves as it is.

$ echo -e "\\\\\e[33mfoo\e[0m"
\foo

It's hard to control a color-reset sequence, so my workaround uses two ANSI color escape sequences, to set it to yellow and back to default.

Paebbels
  • 15,573
  • 13
  • 70
  • 139
  • It doesn't make sense to expect what you expect. Maybe read up on the difference between single and double quotes; https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash – tripleee Sep 15 '18 at 18:23
  • Also; don't use `echo -e` anyway, as it's a portability nightmare. Probably look at `printf` instead. – tripleee Sep 15 '18 at 18:24
  • Single quotes do not expand variables, thus double quotes are required. `printf` has the same behavior regarding triple backslashes. – Paebbels Sep 15 '18 at 18:48
  • Neither `echo` nor `printf` has this behavior wrt triple backslashes. It's an invocation problem. If you do `echo -e "\\\e"` then you are invoking echo with *two* backslashes, not three. – that other guy Sep 15 '18 at 18:52

1 Answers1

4

This happens because there are two levels of escaping at work:

  1. escaping for the double quoted string. This pass recognizes \\ but not \e
  2. echo -e escape sequences. This pass recognizes both \\ and \e.

So:

  1. The initial string is \\\e
  2. The double quotes replace the \\ but leaves the unsupported \e alone
  3. You now have \\e
  4. Echo replaces the \\
  5. You now have \e

This is one of the many reasons why you should prefer printf over echo whenever any value may contain a backslash.

that other guy
  • 116,971
  • 11
  • 170
  • 194
  • `printf` gives you fine grained control over which sequences will or won't be expanded. I have no idea what you're trying to accomplish with your code, but an unrelated example would be `var='\x40'; printf "%s becomes $var\n" "$var"` which prints `\x40 becomes @`, showing the escape sequences in the value both expanded and unexpanded. – that other guy Sep 15 '18 at 18:49
  • The example is shown in listing 1 and 2 of my question. Several color escape sequences are defined and are used in `echo` statements. When writing a \ at the end of a line short before the resetting color sequence, I get 3 backslashes. The \ is used to designate a line continuation. – Paebbels Sep 15 '18 at 18:53
  • 1
    Oh, I see what you mean now. Yes, that's a quoting issue. The parameter you give echo should be `...\\\e...` but due to your quoting you instead give it `...\\e...`, and `echo` understandably does not do what you intended – that other guy Sep 15 '18 at 19:17