12

I have a shell script that uses the following to print a green checkmark in its output:

col_green="\e[32;01m"
col_reset="\e[39;49;00m"

echo -e "Done ${col_green}✓${col_reset}"

After reading about Bash's ANSI-C Quoting, I realized I could use it when setting my color variables and remove the -e flag from my echo.

col_green=$'\e[32;01m'
col_reset=$'\e[39;49;00m'

echo "Done ${col_green}✓${col_reset}"

This seems appealing, since it means the message prints correctly whether it's passed to Bash's builtin echo or the external util /bin/echo (I'm on macOS).

But does this make the script less portable? I know Bash and Zsh support this style of quoting, but I'm not sure about others.

  • Yes, since when only ksh and its variations support it for now. But IIRC, ANSI-C quoting is going to be in next POSIX spec. – cuonglm Jun 18 '17 at 17:41
11

$'…' is a ksh93 feature that is also present in zsh, bash, mksh, FreeBSD sh and in some builds of BusyBox sh (BusyBox ash built with ENABLE_ASH_BASH_COMPAT). It isn't present in the POSIX sh language yet. Common Bourne-like shells that don't have it include dash (which is /bin/sh by default on Ubuntu among others), ksh88, the Bourne shell, NetBSD sh, yash, derivatives of pdksh other than mksh and some builds of BusyBox.

A portable way to get backslash-letter and backslash-octal parsed as control characters is to use printf. It's present on all POSIX-compliant systems.

esc=$(printf '\033') # assuming an ASCII (as opposed to EBCDIC) system
col_green="${esc}[32;01m"

Note that \e is not portable. It's supported by many implementations of printf but not by the one in dash¹. Use the octal code instead.

¹ It is supported in Debian and derivatives that ship at least 0.5.8-2.4, e.g. since Debian stretch and Ubuntu 17.04.

  • are you sure about \e not being supported in dash? dash -c 'printf "\e[1;31m"; type printf; printf "\e[m"' will print printf is a shell builtin in bold red here (dash-0.5.8). A shell that doesn't support \e is yash. – mosvy Feb 19 at 17:35
  • @mosvy Prints \e[1;31mprintf is a shell builtin \e[m here. Ubuntu 16.04, dash 0.5.8-2.1ubuntu2. Prints in red on Ubuntu 18.04 with dash 0.5.8-2.10. Looks like Ubuntu made a patch to support it. – Gilles 'SO- stop being evil' Feb 19 at 17:46
  • Yeah, sorry, it looks that's a debian (9.7 stretch) patch. here's the original. – mosvy Feb 19 at 17:54

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.