Bash Shell脚本输出对齐


29

我的剧本:

date
echo -e "${YELLOW}Network check${NC}\n\n"

while read hostname
do

ping -c 1 "$hostname" > /dev/null 2>&1 &&

echo -e "Network $hostname : ${GREEN}Online${NC}" ||
echo -e "${GRAY}Network $hostname${NC} : ${RED}Offline${NC}"

done < list.txt
        sleep 30
clear
done

正在输出这样的信息:

Network 10.x.xx.xxx : Online   
Network 10.x.xx.xxx : Offline   
Network 10.x.xx.xxx : Offline   
Network 10.x.xx.xxx : Offline   
Network 10.x.xx.x : Online   
Network 139.xxx.x.x : Online   
Network 208.xx.xxx.xxx : Online   
Network 193.xxx.xxx.x : Online

我想清理得到这样的东西:

Network 10.x.xx.xxx       : Online  
Network 10.x.xx.xxx       : Offline   
Network 10.x.xx.xxx       : Offline    
Network 10.x.xx.x         : Online    
Network 139.xxx.x.x       : Online  
Network 208.xx.xxx.xxx    : Online    
Network 193.xxx.xxx.x     : Online  
Network 193.xxx.xxx.xxx   : Offline

Answers:


45

使用printf格式化输出(它也比更便携echo)。我还将存储颜色转义序列的实际值,而不是将其存储为需要扩展为的形式echo

RED=$(tput setaf 1) GREEN=$(tput setaf 2) YELLOW=$(tput setaf 3)
NC=$(tput sgr0) 
online="${GREEN}online$NC" offline="${RED}offline$NC"

ping -c 1 "$hostname" > /dev/null 2>&1 && state=$online || state=$offline
printf 'Network %-15s: %s\n' "$hostname" "$state"

%-15s是一种格式的规范,垫在右侧,以便用空格字符串作为长度(以字符数zshfish在大多数其他shell / printf的字节),以至少为15。

$ printf '|%-4s|\n' a ab abc abcd abcde
|a   |
|ab  |
|abc |
|abcd|
|abcde|
 printf '|%4s|\n' a ab abc abcd abcde
|   a|
|  ab|
| abc|
|abcd|
|abcde|

截断:

$ printf '|%.4s|\n' a ab abc abcd abcde
|a|
|ab|
|abc|
|abcd|
|abcd|
$ printf '|%4.4s|\n' a ab abc abcd abcde
|   a|
|  ab|
| abc|
|abcd|
|abcd|
$ printf '|%-4.4s|\n' a ab abc abcd abcde
|a   |
|ab  |
|abc |
|abcd|
|abcd|

其他用于格式化列中文本格式的实用程序包括POSIXexpand

printf 'Network %s\t: %s\n' "$hostname" "$state" | expand -t 30

(在此\t,每30列用制表位停止扩展TAB字符())

BSDcolumnPOSIXpr

printf 'Network %s\n: %s\n' "$hostname" "$state" | pr -at2

(此处在2个36列宽的列上输出(请参阅-w将页面宽度从默认值72更改为该选项)。

BSDrs

{
   while...
      printf 'Network %s\n: %s\n' "$hostname" "$state"
   done
} | rs -e 0 2

(例如,column直到已读取所有输入,才开始输出)。

GNUcolumns

printf 'Network %s\n: %s\n' "$hostname" "$state" | columns -w 25 -c 2

zsh还有一些用于字符串填充的参数扩展标志:${(l:15:)hostname}用于填充和${(r:15:)hostname}用于填充(带有截断)。在提示扩展中(例如在提示中或在print -P带有参数的参数扩展中启用或已启用%),它还支持%F{green}颜色输出,因此您可以执行以下操作:

online='%F{green}online%f'
printf '%s\n' "Network ${(r:15:)hostname}: ${(%)online}"

要么:

print -rP "Network ${(r:15:)hostname}: $online"

尽管的内容$hostname随后也会迅速扩展,但是如果的内容$hostname不在您的控制之下,则这将构成命令注入漏洞(例如hostname='%<a[`reboot`]<'


35

只需使用column命令:

yourscript.sh | column -t

输出:

Network  10.x.xx.xxx     :  Online
Network  10.x.xx.xxx     :  Offline
Network  10.x.xx.xxx     :  Offline
Network  10.x.xx.xxx     :  Offline
Network  10.x.xx.x       :  Online
Network  139.xxx.x.x     :  Online
Network  208.xx.xxx.xxx  :  Online
Network  193.xxx.xxx.x   :  Online

我为愚蠢的问题感到抱歉,但是我应该在哪里放置该命令?
pijaaa

@pijaaa,请参阅我的更新,并通过脚本输出管道
RomanPerekhrest

10
请注意column(一个BSD命令,也已移植到Linux并在某些发行版中默认存在,不要与GNU混淆columns),在开始输出某些内容之前,需要先读取整个输入,因为它需要计算基于列的宽度在最大的范围内。
斯特凡Chazelas

3

更新您的脚本,以在\t(制表符)您要制表出列的位置插入设置编号。

输出类似于以下内容的内容将为您提供所需的对齐方式:

Network 10.x.xx.xxx\t: Online   
Network 10.x.xx.xxx\t: Offline   
Network 10.x.xx.xxx\t: Offline   
Network 10.x.xx.xxx\t: Offline   
Network 10.x.xx.x\t: Online   
Network 139.xxx.x.x\t: Online   
Network 208.xx.xxx.xxx\t: Online   
Network 193.xxx.xxx.x\t: Online

3
值得在问题中基于脚本添加一个简短的示例...
Stephen Kitt

@StephenKitt ty Stephen,我试图弄清楚如何使它不仅仅是一行,而老实说,这对我没有发生!
djsmiley2k-CoW

3
您会注意到,默认情况下,每8列的制表位printf 'Network %s\t: Online\n' 8.8.8.8 192.168.122.123不能正确对齐。您可以通过使用expand带有其他制表位的选项卡扩展选项卡来解决此问题,如我的答案所示。
斯特凡Chazelas

然后,通过单击对勾图标,随时接受此作为答案。
djsmiley2k-CoW

0

显示比@Roman更好

yourscript.sh | column -t -s $'\t'

然后添加\t每一行以将其拆分为列。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.