Imprimir uma variável multilinha em uma coluna

Imprimir uma variável multilinha em uma coluna

Tenho um script que coleta valores de um cluster. Os valores, em alguns casos, possuem múltiplas linhas. Eu tenho um formato printf que especifica como os dados devem ser posicionados, porém não leva em consideração várias linhas e, portanto, o espaçamento é distorcido.

The data should look like this:

Service Group          AutoStart List          System List
foo                    sys1                    sys1
                       sys2                    sys2

Em vez disso, parece assim

Service Group          AutoStart List          System List
foo                    sys1                    
sys2                    sys1
sys2

A Lista AutoStart e a Lista do Sistema devem ser idênticas, porém, independentemente desse fato, não descobri como forçar os valores nas colunas corretas.

sgheader="\n\033[4m\033[1m%-30s %-30s %-15s\033[0m\033[0m"
sgformat="\n%-30s %-30s %-15s"



printf "${sgheader}" "Service Group" "Autostart List" "System List" 
printf "${sgformat}" "${svcgroup}" "${autostrtlist}" "${hosts}"

Responder1

Talvez algo como:

svcgroup='foo' autostrtlist=$'sys1\nsys2' hosts=$'sys1\nsys2'
paste <(printf '%s\n' "$svcgroup") \
      <(printf '%s\n' "$autostrtlist") \
      <(printf '%s\n' "$hosts") | expand -t30

(sintaxe ksh93/zsh/bash). Ou, POSIXly, em um sistema com /dev/fd/x:

paste /dev/fd/3 3<<E3 /dev/fd/4 4<<E4 /dev/fd/5 5<<E5 | expand -t 30
$svcgroup
E3
$autostrtlist
E4
$hosts
E5

Exceto com dash,yashe versões recentes do bash, que usam arquivos temporários em vez de pipes alimentados por subshells, portanto, provavelmente será mais eficiente (além de ser mais portátil).

Responder2

Você pode remover quaisquer novas linhas de uma variável.

var=$(echo "$var" | tr -d '\n')

Responder3

Se todos eles couberem sempre em uma linha, essas são algumas maneiras fáceis. Se você quiser fazer isso exatamente da maneira que está solicitando, será necessário mais esforço para alinhar as colunas corretamente. Aqui está a ideia básica:

#!/bin/bash

inputA="foo"
inputB=$'sys1\nsys2\n'
inputC=$'sys1\nsys2\n'

sgheader="\033[4m\033[1m%-30s %-30s %-15s\033[0m\033[0m\n"
sgformat="%-30s %-30s %-15s\n"

printf "${sgheader}" "Service Group" "Autostart List" "System List"

# This shows two simple ways to do this which use concatenation but
# require that the result still fit in the same space as is used for
# a single line
columnA="$inputA"
columnB=$(echo "$inputB"|awk '{printf("%s,",$0)}'|sed 's/,.\s*$//')
columnC=$(echo "$inputC"|tr '\n' ',')

printf "${sgformat}" "${columnA}" "${columnB}" "${columnC}"

# This is a version which outputs like originally asked. It is much harder
# to tweak the formatting of this version though.
pr -tm <(printf '%s\n' "$inputA") <(printf '%s\n' "$inputB") \
       <(printf '%s\n' "$inputC") | expand -t10

A melhor maneira que conheço de fazer isso do jeito que você quer é bagunçada. Mesmo depois disso, você pode querer refinar ainda mais a saída para alinhá-la corretamente.

informação relacionada