Desde que me lembro, usei pessoalmente o seguinte método para alterar a cor do texto de saída ao usar o bash:
red=$'\033[1;31m'
nc=$'\033[0m'
echo "${red}This is red text$nc"
Sempre funcionou para mim, não importa se usado no macOS ou no Linux. Por curiosidade, para entender melhor porque funciona, pesquisei um pouco e encontrei algumas respostas/exemplos que não incluem $
( red='\033[1;31m'
). Após alguns testes, se eu não usar $
, a cor de saída não muda para vermelho, apenas imprime a string. No entanto, ao executá-lo usando sh
em vez de bash
, o texto muda de cor. Alguém pode me ajudar a entender o porquê disso?
Além disso, testei com aspas duplas em vez de aspas simples, e parece funcionar apenas ao usar sh
. Vou postar exemplos abaixo.
Este é o script e o código que usei:
#!/bin/bash
red=$'\033[1;31m'
nc=$'\033[0m'
echo "${red}Test 1$nc"
echo ""
##########################
red=$"\033[1;31m"
nc=$"\033[0m"
echo "${red}Test 2$nc"
echo ""
##########################
red='\033[1;31m'
nc='\033[0m'
echo "${red}Test 3$nc"
echo ""
##########################
red="\033[1;31m"
nc="\033[0m"
echo "${red}Test 4$nc"
echo ""
Saída no macOS com bash e sh:
Saída no Linux com bash e sh:
O principal aqui é que para o terminal reconhecer a sequência de controle, a saída enviada ao terminal deve conter o caractere ESC, então
[1;31m
. Esse ESC é um caractere de controle e geralmente não o apresentamos como está em um script de shell, mas usamos o escape de barra invertida\033
para representar esse caractere usando seu código de caractere octal (é 27 decimal, 033 octal ou 0x1b hex ). O resto são apenas personagens normais.Agora, esse escape de barra invertida precisa ser alterado para o caractere ESC bruto em algum momento. E há dois lugares onde isso pode acontecer: a atribuição à variável e o comando que a imprime.
Nos shells que o suportam, o
$'...'
tipo de aspas já interpreta o escape, portanto, depoisred=$'\033[...'
de , a própria variável contém o caractere ESC bruto. Esse não é um recurso POSIX padrão e, em shells que não o suportam, isso atribuiria o cifrão bruto, depois a barra invertida033[
e assim por diante. Por outro lado,red='\033[...'
apenas atribuiria uma barra invertida,033[
etc., nunca interpretando o escape. Ver(
$"..."
, e"..."
nunca interprete o escape, e aquele com o dólar também não é padrão, portanto, pode deixar o cifrão literal em shells que não o suportam.)Em seguida, a segunda etapa é a impressão. Em alguns shells
echo
expande escapes de barra invertida. Em outros não. Alguns desses têmecho -e
que novamente faz. O Bashecho
por padrão não faz isso, mas com axpg_echo
configuração definida ... Zsh osecho
interpreta. VerPortanto, em um Bash usual em sua distribuição de desktop Linux usual, onde
xpg_echo
não está definido,red=$'\033[1;31m'; echo "${red}text"
produz o ESC na atribuição e imprime o texto em vermelho, masred='\033[1;31m'; echo "${red}text"
não o produz na atribuição ou noecho
e apenas imprime\033[1;31mtext
na cor normal.No Debian/Ubuntu,
sh
é o Dash, onde as$'...'
aspas não são suportadas, masecho
interpretam barras invertidas, entãored=$'\033[1;31m'; echo "${red}text"
imprime um texto de cor normal e$
, em seguida, o texto vermelho. É assim que você corresh
e o Linux se parece. Você pode obter um resultado diferente em algum outro sistema Linux.E em um Mac, o shell instalado como
sh
é, na verdade, Bash comxpg_echo
set (aquele instalado comobash
desabilitado) ou zsh em versões mais recentes do macOS. Mesmo que comecem comosh
tentativas de torná-los mais compatíveis com POSIX, eles ainda suportam as$'...'
aspas, então ambosred=$'\033[1;31m'; echo "${red}text"
ered='\033[1;31m'; echo "${red}text"
imprimem texto em vermelho.Confuso ainda?
red='\033[1;31m'; printf "%b\n" "${red}text";
deve funcionar em todos os shells do tipo POSIX. O%b
diz para processar escapes de barra invertida no argumento, para que qualquer um em "texto" seja processado.Eu posso responder pelo Linux. e acho que o ponto crucial não é como usar as seqüências de escape ANSI, mas como declarar uma variável.
Em
sh
, ao imprimir comvocê imprime o valor da variável
red
e, em seguida, algum texto. Nos dois primeiros casos, há um cifrão antes da sequência de escape ANSI, portanto, não é afetado pela mudança de cor.Em
bash
, ao imprimir coma sequência de escape ANSI é interpretada, mas com
a seqüência de escape ANSI não é interpretada, em vez disso, os caracteres são impressos literalmente, mas podem ser convertidos 'antes' da
echo
instrução.No seu
sh
existe outra funçãoecho
interna que obviamente interpreta a sequência de escape ANSI sem a opção-e
.A diferença para você
bash
entre o primeiro e os outros exemplos pode ser explicada se você observar o valor hexadecimal dered
. Veja meu roteiro editado,onde também facilitei a visualização
echo -e
adicionando essa opção ao script, então tente os doise
Sugiro que você declare suas variáveis de 'coloração' sem nenhum cifrão, por exemplo
e use o cifrão apenas quando usar uma variável, por exemplo, em uma
echo
instrução.