É possível usar códigos de escape de cor ANSI em Bash here-documents?

6

Estou imprimindo uma mensagem em um script Bash e quero colorir uma parte dela; por exemplo,

#!/bin/bash

normal='\e[0m'
yellow='\e[33m'
cat <<- EOF
    ${yellow}Warning:${normal} This script repo is currently located in:
    [ more messages... ]
EOF

Mas quando eu executo no terminal ( tmux inside gnome-terminal ) os caracteres de escape ANSI são impressos em \ form; por exemplo,

\e[33mWarning\e[0m This scr....

Se eu mover a parte que eu quero colorir para um comando printf fora do aqui-doc, ele funciona. Por exemplo, isso funciona:

printf "${yellow}Warning:${normal}"
cat <<- EOF
    This script repo is currently located in:
    [ more messages... ]
EOF

De man bash - aqui Documentos:

No parameter and variable expansion, command substitution, arithmetic expansion, or pathname expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion.  In the latter case, the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and '.

Não sei como isso afetaria os códigos de escape ANSI. É possível usar códigos de escape ANSI em um documento Bash aqui que é cat ted?

    
por the_velour_fog 02.03.2016 / 01:20

2 respostas

23

No seu script, essas atribuições

normal='\e[0m'
yellow='\e[33m'

coloque os caracteres literalmente nas variáveis, ou seja, \ e [ 0 m , em vez da sequência de escape. Você pode construir um caractere de escape usando printf (ou algumas versões de echo ), por exemplo,

normal=$(printf '3[0m')
yellow=$(printf '3[33m')

mas você faria muito melhor usar tput , pois isso funcionará para qualquer terminal configurado corretamente:

normal=$(tput sgr0)
yellow=$(tput setaf 3)

Olhando para o seu exemplo, parece que a versão de printf que você está usando trata \e como o caractere de escape (que pode funcionar em seu sistema, mas geralmente não é portável para outros sistemas). Para ver isso, tente

yellow='\e[33m'
printf 'Yellow:%s\n' $yellow

e você veria os caracteres literal :

Yellow:\e[33m

em vez da sequência de escape. Colocá-los no formato printf informa ao printf para interpretá-los (se puder).

Leitura adicional:

por 02.03.2016 / 01:24
2

Essas atribuições não estão colocando caracteres de escape na variável:

normal='\e[0m'                  yellow='\e[33m'

Para fazer isso, você precisa de echo -e printf ou $'...' (no bash).

Como você está usando o bash, é melhor usar isso:

normal=$'\e[0m'                 yellow=$'\e[33m'

Por favor, note o $ antes da string '\e[0m' .

No entanto, a maneira portátil de obter caracteres com escape é printf, como este:

normal="$(printf '3[0m')"    yellow="$(printf '3[33m')"

O valor octal (033) do caractere de escape é válido em todas as camadas POSIX.

    
por 02.03.2016 / 03:19