Why doesn't echo support "\e" (escape) when using the -e argument in MacOSX

36

9

When I try to print out some colored text using ANSI escape sequences via the built-in echo command, it seems that the \e escape sequence in the string I provide is interpreted literally instead of as the "escape" it's supposed to represent. This only happens in Snow Leopard -- the examples below work as intended in Leopard.

Apparently echo does support the -e switch since it correctly interprets \n when using it:

~ $ 
~ $ echo "\n"
\n
~ $ echo -e "\n"


~ $ 

But when I try to use \e, I get this:

~ $ echo -e "\e[34mCOLORS"
\e[34mCOLORS
~ $ 

Like I said, in Leopard, the above would give me the string "COLORS" in color.

Does anyone know of a reason why this might be an intended change? How about a workaround for printing ANSI escape sequences from Bash scripts on Snow Leopard?

The Bash shell version on my Leopard machine is 3.2.17(1)-release and 3.2.48(1)-release on my Snow Leopard machine.

hasseg

Posted 2009-09-01T21:24:46.173

Reputation: 956

1The question contradicts the post. In the question you refer to /bin/echo, while in the post you use echo without path, which most probably is the builtin echo of your shell. – 0x89 – 2009-09-03T16:28:02.473

Of course -- thanks for noticing. I fixed the question to reflect this. – hasseg – 2009-09-05T18:25:09.797

Answers

25

I cannot tell you why it does not support that argument (you may have to ask the programmers about that). I only know that on my linux box, I get this:

$ /bin/echo --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
  or:  /bin/echo LONG-OPTION
Echo the STRING(s) to standard output.

  -n             do not output the trailing newline
  -e             enable interpretation of backslash escapes
  -E             disable interpretation of backslash escapes (default)
      --help     display this help and exit
      --version  output version information and exit

If -e is in effect, the following sequences are recognized:
*emphasized text*
  \0NNN   the character whose ASCII code is NNN (octal)
  \\     backslash
  \a     alert (BEL)
  \b     backspace
  \c     produce no further output
  \f     form feed
  \n     new line
  \r     carriage return
  \t     horizontal tab
  \v     vertical tab

NOTE: your shell may have its own version of echo, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.

Report echo bugs to bug-coreutils@gnu.org
GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
General help using GNU software: <http://www.gnu.org/gethelp/>
Report echo translation bugs to <http://translationproject.org/team/>
  • this does not mention \e escapes
  • it says that it is /bin/echo from gnu coreutils. As apple changes the source of their unix-system components from time to time (e.g. move from zsh to bash), check if there was a change for /bin/echo between Leopard and Snow Leopard. If it is gnu, you can ask the people at gnu.org why they choose not to include those sequences.

As for workarounds (thats more interesting): Not using /bin/echo, but bash's builtin echo works on linux boxes. If they changed to a bash without builtin echo (or something even more obscure), you could also try this not widely known feature of your shell (works at least in bash and zsh):

$ echo $'\e[34m''COLORS'

This is the matching part of bash's manpage:

   Words  of  the  form  $'string' are treated specially.  The word expands to string, with
   backslash-escaped characters replaced as specified by the ANSI  C  standard.   Backslash
   escape sequences, if present, are decoded as follows:
          \a     alert (bell)
          \b     backspace
          \e     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \nnn   the  eight-bit  character whose value is the octal value nnn (one to three
                 digits)
          \xHH   the eight-bit character whose value is the hexadecimal value  HH  (one  or
                 two hex digits)
          \cx    a control-x character

   The expanded result is single-quoted, as if the dollar sign had not been present.

   A  double-quoted string preceded by a dollar sign ($) will cause the string to be trans‐
   lated according to the current locale.  If the current locale is C or POSIX, the  dollar
   sign  is  ignored.  If the string is translated and replaced, the replacement is double-
   quoted.

0x89

Posted 2009-09-01T21:24:46.173

Reputation: 969

1\e is not part of the POSIX standard; the GNU coreutils implementation extended on the standard. OS X did not. – Martijn Pieters – 2017-11-05T12:32:08.050

4I wasn't aware of $'string' being escape sequence -enabled, thanks. – hasseg – 2009-09-05T18:20:19.887

49

Try \x1B instead of \e.

LiraNuna

Posted 2009-09-01T21:24:46.173

Reputation: 1 664

6\x1B instead of \e does work, thanks. – hasseg – 2009-09-05T18:19:15.643

10

Just for reference, 1B is the hex value of the Escape character.

– TachyonVortex – 2013-09-21T16:25:06.170

15

Does \033 still work? If not, you can hopefully press Ctrl+V followed by the Escape key (if a mac has those keys) to create a real control character inside the command line (which does not work that well in scripts of course, depending on the editor)

mihi

Posted 2009-09-01T21:24:46.173

Reputation: 3 217

Just for future reader reference 033 would be standardised way to write octal. – ocodo – 2016-07-12T03:27:08.667

5\033 instead of \e does work, thanks. – hasseg – 2009-09-05T18:18:44.523

4

Just for reference, 33 is the octal value of the Escape character.

– TachyonVortex – 2013-09-21T16:25:34.157

11

One other way of printing ANSI escape sequences in the shell is by using /usr/bin/printf.

hasseg

Posted 2009-09-01T21:24:46.173

Reputation: 956

3printf is the portable way of displaying things in shell. There are too many flavours of echo... – mouviciel – 2009-09-05T19:56:18.817

6

To complement the existing helpful answer with some background information:

If you're invoking echo by name only - as opposed to with its path, /bin/echo - you're invoking the Bash builtin rather than the external utility.

The behavior of native Bash elements such as builtins is typically portable in a Bash sense, meaning they should work the same on any platform capable of running Bash.

\e is a curious exception that affects 3.x Bash versions on macOS (to this day, as of v10.13.5 (High Sierra), macOS comes with outdated 3.x versions of Bash, for legal reasons).

\e (and its alias \E) should work with echo -e; \e support was added to the echo builtin in Bash 2.0., but inexplicably doesn't in the 3.x stock version on macOS.

\e does work in 3.x Bash versions on other platforms, such as MSYS on Windows.

Conversely, if you install and use a 4.x Bash on macOS, \e does work.

mklement0

Posted 2009-09-01T21:24:46.173

Reputation: 1 519

2

They might try to conform to POSIX: http://www.opengroup.org/onlinepubs/9699919799/

Part OPTIONS states among other things:

Implementations shall not support any options.

Caotic

Posted 2009-09-01T21:24:46.173

Reputation: 121

Nope. The page continues to write: ‘If the first operand is -n, or if any of the operands contain a <backslash> character, the results are implementation-defined.’ Also, the macOS echo does interpret -e. – Yongwei Wu – 2019-07-26T06:08:15.833

Here is the direct link to the material I think you intended: http://www.opengroup.org/onlinepubs/9699919799/utilities/echo.html

– Paused until further notice. – 2009-11-01T02:21:26.530

2

FYI, We're just about to add \e support to /bin/echo and /usr/bin/printf in coreutils. Note the C standards do not specify \e, but gcc, perl, bash, ksh and tcsh support it

pixelbeat

Posted 2009-09-01T21:24:46.173

Reputation: 950

0

You might check if ,,escape non-ascii characters'' have been un-checked in the view options menu of the terminal.app.

Tadeusz A. Kadłubowski

Posted 2009-09-01T21:24:46.173

Reputation: 2 005