Os shells que não sejam o Bash e o Zsh suportam citações ANSI-C? por exemplo, $ 'string'


13

Eu tenho um script de shell que usa o seguinte para imprimir uma marca de seleção verde em sua saída:

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

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

Depois de ler sobre a cotação ANSI-C da Bash , percebi que poderia usá-la ao definir minhas variáveis ​​de cores e remover a -esinalização do meu eco .

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

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

Isso parece atraente, pois significa que a mensagem é impressa corretamente, seja passada para o eco interno do Bash ou para o utilitário externo /bin/echo(estou no macOS).

Mas isso torna o script menos portátil? Eu sei que o Bash e o Zsh apóiam esse estilo de citação, mas não tenho certeza sobre os outros.


Sim, desde quando apenas o ksh e suas variações o suportam por enquanto. Mas as cotações do IIRC, ANSI-C estarão na próxima especificação do POSIX.
cuonglm

Respostas:


12

$'…'é um recurso do ksh93 que também está presente no zsh, bash, mksh, no FreeBSD sh e em algumas versões do BusyBox sh (o BusyBox ash é construído com ENABLE_ASH_BASH_COMPAT). Ainda não está presente na linguagem sh POSIX. Os shells comuns do tipo Bourne que não o incluem incluem dash (que é /bin/shpor padrão no Ubuntu, entre outros), ksh88, o shell Bourne, NetBSD sh, yash, derivados do pdksh que não o mksh e algumas versões do BusyBox.

Uma maneira portátil de obter a barra invertida e a barra invertida octal como caracteres de controle é usar printf. Está presente em todos os sistemas compatíveis com POSIX.

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

Observe que \enão é portátil. É suportado por muitas implementações, printfmas não pela que está no painel¹. Use o código octal.

¹ É suportado no Debian e derivados que são enviados pelo menos 0.5.8-2.4, por exemplo, desde o Debian stretch e Ubuntu 17.04.


Tem certeza de que \enão é suportado dash? dash -c 'printf "\e[1;31m"; type printf; printf "\e[m"'será impresso printf is a shell builtinem vermelho negrito aqui (traço-0.5.8). Um shell que não suporta \eé yash.
mosvy

@mosvy Imprime \e[1;31mprintf is a shell builtin \e[maqui. Ubuntu 16.04, traço 0.5.8-2.1ubuntu2. Imprime em vermelho no Ubuntu 18.04 com o traço 0.5.8-2.10. Parece que o Ubuntu fez um patch para apoiá-lo.
Gilles 'SO- stop be evil'

Sim, desculpe, parece que é um patch do debian (9.7 stretch). aqui está o original.
mosvy

0

O grau de $'...'suporte também precisa ser levado em consideração ao transportar. A proposta do POSIX Folks de colocar isso no POSIX sh menciona uma em particular:

stephane: ksh93 é o shell $ '...' vem (enquanto $'\uxxxx'[ e$'\Uxxxxxxxx' ] vem do zsh: http://www.zsh.org/mla/workers/2003/msg00223.html ) [^]

Pelo que cheguei aqui no meu alvo Debian, a ksh2020da AT&T entende $'\U1F600'. Este é o único shell "oficial" do Korn que posso obter nesta nova distribuição.

mkshanalisou, mas estragou tudo com um U + FFFE. Como não se queixou de um erro de sintaxe, deve haver algo errado com a compreensão do Unicode. Ele lida $'\U01F60'muito bem.


Infelizmente, como efeito de um golpe recente, o ksh2020 desapareceu. Mas sim, o ksh93 original suporta $'...'e o iirc foi o primeiro a fazê-lo.
mosvy

@ Arthur2e5. ksh2020não é da AT&T. Duas pessoas, uma da Red Hat, essencialmente sequestraram a árvore do github da AT&T AST há alguns anos e reivindicaram o controle do ksh93desenvolvimento futuro
fpmurphy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.