Распечатать многострочную переменную в столбце

Распечатать многострочную переменную в столбце

У меня есть скрипт, который собирает значения из кластера. Значения в некоторых случаях имеют несколько строк. У меня есть формат printf, который определяет, как должны быть расположены данные, однако он не учитывает несколько строк, и поэтому интервалы перекошены.

The data should look like this:

Service Group          AutoStart List          System List
foo                    sys1                    sys1
                       sys2                    sys2

Вместо этого это выглядит так

Service Group          AutoStart List          System List
foo                    sys1                    
sys2                    sys1
sys2

Список автозапуска и список систем должны быть идентичны, однако, несмотря на это, я не придумал, как принудительно разместить значения в правильных столбцах.

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

решение1

Может быть, что-то вроде:

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

(синтаксис ksh93/zsh/bash). Или, POSIXly, в системе с /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

За исключением dash,yashи последние версии bash, в которых используются временные файлы вместо каналов, подаваемых подоболочками, поэтому они, вероятно, более эффективны (в дополнение к большей переносимости).

решение2

Вы можете удалить любые новые строки из переменной.

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

решение3

Если они все будут помещаться на одной строке каждый раз, то вот несколько простых способов. Если вы хотите сделать это именно так, как вы просите, то потребуется больше усилий, чтобы выстроить столбцы правильно. Вот основная идея:

#!/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

Лучший известный мне способ сделать это так, как вам нужно, — беспорядочный. Даже после этого вы можете захотеть еще больше уточнить вывод, чтобы выстроить его правильно.

Связанный контент