我有一个从集群收集值的脚本。在某些情况下,这些值有多行。我有一个 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
,它使用临时文件而不是由子 shell 提供的管道,因此可能更高效(除了更便携之外)。
答案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
据我所知,按照您想要的方式执行此操作的最佳方法是混乱的。即使在那之后,您可能还想进一步细化输出以正确排列。