bash +使用printf以特殊格式打印


12

我刚刚编写了以下bash脚本来检查Linux机器列表上的ping访问:

for M in $list
 do
   ping -q -c 1  "$M" >/dev/null 
          if [[ $? -eq 0 ]]
   then
    echo "($C) $MACHINE CONNECTION OK"
   else
    echo "($C) $MACHINE CONNECTION FAIL"
   fi

   let C=$C+1
done

打印:

 (1) linux643 CONNECTION OK
 (2) linux72 CONNECTION OK
 (3) linux862 CONNECTION OK
 (4) linux12 CONNECTION OK
 (5) linux88 CONNECTION OK
 (6) Unix_machinetru64 CONNECTION OK

如何printf在bash脚本中使用(或任何其他命令)以打印以下格式?

 (1) linux643 ............ CONNECTION OK
 (2) linux72 ............. CONNECTION OK
 (3) linux862 ............ CONNECTION OK
 (4) linux12 ............. CONNECTION OK
 (5) linux88 ............. CONNECTION FAIL
 (6) Unix_machinetru64 ... CONNECTION OK

您可以进行计算$TOTAL (length) - $MASHINE (length)以获得点数。然后printf '.%.s' {1..$DOTS}在每个循环迭代中使用。我认为这样的事情会起作用。
coffeMug

您能否将您的解决方案描述为答案
yael

您已经有了答案。;-)
coffeMug

Answers:


19

使用参数扩展替换%-s由点引起的空格:

#!/bin/bash
list=(localhost google.com nowhere)
C=1
for M in "${list[@]}"
do
    machine_indented=$(printf '%-20s' "$M")
    machine_indented=${machine_indented// /.}

    if ping -q -c 1  "$M" &>/dev/null ;  then
        printf "(%2d) %s CONNECTION OK\n" "$C" "$machine_indented"
    else
        printf "(%2d) %s CONNECTION FAIL\n" "$C" "$machine_indented"
    fi
    ((C=C+1))
done

哇,让我检查一下,我会尽快更新........................
yael 2016年

1
嘿,聪明!几个有趣的观点:i)在%2d括号内添加了一个不必要的空间(尽管在$ list> = 10时可能有用);ii)为了获得OP的确切输出,您可能需要machine_indented=${machine_indented/../ .}在first之前添加一个额外的空间.。就像我说的那样
terdon

嗨,乔罗巴(Choroba),您能在回答中考虑泰登语吗?
2016年

@yael:现在应该可以轻松地调整解决方案了:-)
choroba

顺便说一句-为什么要在&/ dev / null之前添加&?
2016年

8

for m in $listzsh语法。在bashfor i in "${list[@]}"

bash没有填充运算符。您可以printf使用空格进行填充,但只能使用空格进行填充,不能使用任意字符进行填充。zsh具有填充运算符。

#! /bin/zsh -
list=(
  linux643
  linux72
  linux862
  linux12
  linux88
  Unix_machinetru64
)
c=0
for machine in $list; do
  if ping -q -c 1 $machine >& /dev/null; then
    state=OK
  else
    state=FAIL
  fi
  printf '%4s %s\n' "($((++c)))" "${(r:25::.:):-$machine } CONNECTION $state"
done

填充操作是${(r:25:)parameter} -pad与长度25与空格或${(r:25::string:)parameter}与任何字符串而不是空间-pad。

我们还可以使用- printf '%4s'来将空格用- 左键填充(x)。我们本来可以使用${(l:4:):-"($((++c)))"}。但是,一个显着的区别是,如果字符串长度超过4个字符,${(l)}则会截断它,而会导致溢出printf


6

%s格式说明可以采取精度(%.20s例如),同样,当你想输出一个浮点值到一定的精度(以%.4f为例),输出将是最多从给定的字符串参数的字符。

因此,创建一个包含机器名称和足以用完点的点的字符串:

cnt=0
for hname in vboxhost ntp.stupi.se example.com nonexistant; do
   if ping -q -c 1  "$hname" >/dev/null 2>&1; then
       status="OK"
   else
       status="FAIL"
   fi

   printf "(%d) %.20s CONNECTION %s\n" \
       "$(( ++cnt ))" "$hname ...................." "$status"

done

输出:

(1) vboxhost ........... CONNECTION OK
(2) ntp.stupi.se ....... CONNECTION OK
(3) example.com ........ CONNECTION OK
(4) nonexistant ........ CONNECTION FAIL

2

从@choroba的答案中偷来的东西:

#!/bin/bash 
list=(linux643 linux72 google.com linux862 linux12 linux88 unix_machinetru64) 
C=1 
readonly TOTAL=50 
for M in "${list[@]}" 
do 
    DOTS=$(( TOTAL - ${#M} ))
    ping -q -c 1  "$M" &>/dev/null 

    if (($?)) ;  then 
        printf "(%d) %s" "$C" "$M" ; printf "%0.s." $(seq 1 $DOTS) ; printf " CONNECTION FAILED\n" 
    else 
        printf "(%d) %s" "$C" "$M" ; printf "%0.s." $(seq 1 $DOTS) ; printf " CONNECTION OK\n"  
    fi 
    ((C=C+1)) 
done 

2

我会用fpingawk。不幸的是,awkprintf不能用点垫,只能用空格或零,所以我必须写一个函数:

list=(kali surya indra ganesh durga hanuman nonexistent)

fping "${list[@]}" 2>&1 | 
  sort -k3 |
  awk -F'[: ]' 'BEGIN { fmt="(%02d) %s CONNECTION %s\n"};

       function dotpad(s,maxlen,     l,c,pads) {
         l = maxlen - length(s);
         pads = "";
         for (c=0;c<l;c++) {pads=pads"."};
         return s " " pads
       };

       /alive$/       { printf fmt, ++i, dotpad($1,19), "OK" };
       /unreachable$/ { printf fmt, ++i, dotpad($1,19), "FAIL" }
       /not known$/   { printf fmt, ++i, dotpad($1,19), "IMPOSSIBLE" } '
(01) durga .............. CONNECTION OK
(02) ganesh ............. CONNECTION OK
(03) indra .............. CONNECTION OK
(04) kali ............... CONNECTION OK
(05) nonexistent ........ CONNECTION IMPOSSIBLE
(06) hanuman ............ CONNECTION FAIL
(07) surya .............. CONNECTION FAIL

我在括号中使用零填充的2位数字,因此,如果其中有10-99个主机,格式不会搞砸$list(100个以上仍会搞砸)。另一种方法是对延迟打印直到END {}块,和用于/正则表达式匹配次数/只插入主机名分成三个阵列中的一个,例如okfailunknown。或仅一个关联数组(例如hosts[hostname]="OK")。然后,您可以计算行数,并用它来决定行数计数器字段的宽度。

我还决定让输出区分未知主机(CONNECTION IMPOSSIBLE)和不可达主机(CONNECTION FAIL)。

sort -k3是可选的,它只是组由输出fping结果(“主机名是活的”,“主机不可达”或“主机名:姓名或不知道服务”)。如果不使用sort,未知主机将始终在输出中首先出现。只是简单sort而没有-k3遗嘱将按主机名排序。

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.