Imprimir una variable multilínea en una columna

Imprimir una variable multilínea en una columna

Tengo un script que recopila valores de un clúster. Los valores, en algunos casos, tienen varias líneas. Tengo un formato printf que especifica cómo se deben colocar los datos; sin embargo, no tiene en cuenta varias líneas y, por lo tanto, el espaciado está sesgado.

The data should look like this:

Service Group          AutoStart List          System List
foo                    sys1                    sys1
                       sys2                    sys2

En cambio se ve así

Service Group          AutoStart List          System List
foo                    sys1                    
sys2                    sys1
sys2

La Lista de inicio automático y la Lista del sistema deberían ser idénticas; sin embargo, independientemente de ese hecho, no he descubierto cómo forzar los valores en las columnas correctas.

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}"

Respuesta1

Quizás 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

(sintaxis ksh93/zsh/bash). O, POSIXly, en un sistema con /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

Excepto con dash,yashy versiones recientes de bash, que utilizan archivos temporales en lugar de tuberías alimentadas por subcapas, por lo que es probable que sea más eficiente (además de ser más portátil).

Respuesta2

Puede eliminar cualquier línea nueva de una variable.

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

Respuesta3

Si todos caben en una línea cada vez, estas son algunas formas sencillas. Si desea hacer esto exactamente de la manera que lo solicita, requerirá más esfuerzo alinear las columnas correctamente. Aquí está la idea 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

La mejor manera que conozco de hacer esto de la manera que deseas es complicada. Incluso después de eso, es posible que desees refinar aún más la salida para alinearla correctamente.

información relacionada