Pode haver três maneiras simples de corrigir isso:
- sempre use sequências de escape nessas colunas para manter o mesmo comprimento
- coloque os escapes em suas próprias colunas (4 colunas extras), embora isso adicione espaço em branco extra na saída
- formata depois de
column
, como você sugeriu
Algumas outras considerações podem ser encontradas aqui: Uma ferramenta de shell para" tablify "dados de entrada contendo códigos de escape ANSI .
Para a primeira opção, em vez de usar apenas 3[1;31m
para vermelho use 3[31;1m
para vermelho e 3[31;0m
para "não vermelho" ou simples - o código 0 desfaz qualquer código anterior, mesmo aqueles na mesma sequência . Então todas as colunas têm o mesmo tamanho de códigos de escape.
BEGIN { FS=OFS="|" }
function colour(ss,cc) { return "3[" cc ";1m" ss "3[0m"; }
function notcolour(ss,cc) { return "3[" cc ";0m" ss "3[0m"; }
{
if ($13~/(RI|PG)/) { $13=colour($13,31) }
else { $13=notcolour($13,31) }
if (($11+0) > 5.8) { $11=colour($11,33) }
else { $11=notcolour($11,33) }
print $1, $2, $5, $10, $11, $13
}
(Há uma série de pequenas simplificações e correções aplicadas no acima também, incluindo uma para coincidir com alterações nos dados de origem.)
O problema com essa abordagem é que ela depende de seu column
e libc
. (Meu column
do util-linux-2.23.2) não verifica o código de retorno de wcswidth()
, que é -1 quando são encontradas não imprimíveis, em vez da largura real; isso realmente atrapalha a formatação da tabela. A última versão do util-linux-2.30.1 usa um novo < em> libsmartcols que resolve este problema, mas faz isso substituindo as não-imprimíveis por uma versão \x
hex-codificada - então você perde as fugas brutas: / Que você pode consertar com a deselegante :
curl ... | awk ... | column -t -s '|' | while read -r line; do printf "$line\n"; done
em que printf
interpreta as fugas. Você poderia substituir 3
por \x1b
em seu próprio código para o mesmo efeito. Eu não tenho certeza se você está usando Linux.)
Para a terceira opção, você precisará de um column
que suporte -o
para definir o separador de saída, o padrão é dois espaços. Defina como " |
", então você pode usar isto:
curl ... | column -t -s "|" -o "|" | awk '
BEGIN { FS="|" }
function colour(ss,cc) { return sprintf("3[%i;1m%s3[0m",cc,ss) }
{
if ($13~/(RI|PG)/) { $13=colour($13,31) }
if (($11+0) > 5.8) { $11=colour($11,33) }
print $1, $2, $5, $10, $11, $13
}'
O truque aqui é usar column
com entrada delimitada por pipe e saída, ele corrige as larguras e podemos seguramente processar isso com awk
, preservando todos os espaços importantes. Se o seu column
não suporta -o
, você pode fingir com:
curl ... | sed -e 's/|/^|/g' | column -t -s^ | awk ...
Isso duplica o separador para " ^|
", column
usa ^
e o awk usa |
. Isso faz com que a suposição de que ^
não apareça nos dados é claro. Uma guia difícil pode funcionar em vez disso.
Eu acho que você sabe o "porquê" agora, mas para ser claro:
-
column
pode contar octetos (ou caracteres) ingenuamente comstrlen()
/wcslen()
, isso não corresponderá ao comprimento processado pelo terminal -
column
pode contar o comprimento usandoisprint()
, também incorreto com escapes de terminal -
column
pode desistir (como o meu) em qualquer coluna quando não imprimíveis forem encontrados
Embora a remoção de sequências de código de cores seja um problema razoavelmente direto, não há uma maneira robusta de contornar isso sem ter um pedaço do emulador de terminal ANSI dentro de column
.