Como exibir dados em colunas em duas variáveis com o mesmo formato?

0

Codifiquei o seguinte para exibir dados formatados em colunas:

str1='hello i      am robert
and your ma frnd'

str2='thisisaverylongword thisistoohehehe andherefinishthe         string
hereis a other linefortheexample'

IFS=$'\n'
echo '----------------------'
echo 'STRING SHORT'
echo '----------------------'
echo "$str1" | column -t
echo
echo '----------------------'
echo 'STRING LONG'
echo '----------------------'
echo "$str2" | column -t

Quais resultados:

----------------------
STRING SHORT
----------------------
hello  i     am  robert
and    your  ma  frnd

----------------------
STRING LONG
----------------------
thisisaverylongword  thisistoohehehe  andherefinishthe  string
hereis               a                other             linefortheexample

Ok, agora estou tentando formatar a string com o mesmo padrão, mas sem mesclá-las.

Este é o resultado que estou procurando:

----------------------
STRING SHORT
----------------------
hello                i                am                robert
and                  your             ma                frnd

----------------------
STRING LONG
----------------------
thisisaverylongword  thisistoohehehe  andherefinishthe  string
hereis               a                other             linefortheexample

Você tem alguma ideia para fazer isso? Pode ser mesclar as strings e dividi-lo antes do formato?

Note que este é apenas um exemplo, estou procurando uma solução genérica, não apenas para este caso específico.

    
por harrison4 23.03.2014 / 19:05

1 resposta

3

Você terá que

printf "%s\n" "$str1" "$str2" | column -t

e então injetam os cabeçalhos

Geralmente, eu escrevo algo assim que usa matrizes:

strings=( "$str1" "$str2" ... )
headers=( "STRING SHORT" "STRING LONG" ... )

exec 3< <( printf "%s\n" "${strings[@]}" | column -t )
for (( i=0; i<${#strings[@]}; i++)); do
    printf -- "----\n%s\n----\n" "${headers[i]}"
    n=$(wc -l <<< "${strings[i]}")
    for (( j=1; j<=n; j++ )); do
        IFS= read -r line <&3
        echo "$line"
    done
    echo
done
exec 3<&-

Notas:

  • <( ... ) é uma substituição de processos da bash. Esse é um pipeline simples que é tratado como um nome de arquivo. É muito útil em situações em que você usaria um cano, mas não pode ter o lado direito do cano executado em uma subcamada.
  • aqui, estamos abrindo o descritor de arquivo nº 3 para ler os dados desse "arquivo": exec 3<file
  • read -r line <&3 lê uma linha de dados da substituição do processo
  • exec 3<&- fecha o descritor de arquivo
  • leia mais sobre redirecionamentos aqui: link
  • Eu poderia ter usado um printf ... | while read line; do ...; done , mas achei que os loops for facilitariam a contagem.
por 23.03.2014 / 21:44