bash +特殊な形式で印刷するためにprintfを使用


12

Linuxマシンのリストでpingアクセスを確認するために、次のbashスクリプトを作成しました。

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 ​​2016年

あなたの解決策を答えとして説明してください
yael

あなたはすでに答えを持っています。;-)
coffeMug ​​2016年

回答:


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


1
へえ、賢い!いくつかの注意点:i)%2d括弧内に不要なスペースが追加されています(ただし、$ list> = 10の場合に便利です)。ii)OPの正確な出力を取得するmachine_indented=${machine_indented/../ .}には、最初のの前にスペースを追加して追加することができ.ます。私が言ったように、知識人。
terdon

こんにちは、チョロバ、あなたはあなたの答えでterdon発言を考慮していただけますか?
yael

@yael:ソリューションを微調整するのが簡単になりました:-)
チョロバ

ところで、なぜ> / dev / nullの前に追加するのですか?
yael 2016年

8

for m in $listあるzsh構文。でbash、それだろうfor 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}右のスペースを長さ25または-pad ${(r:25::string:)parameter}代わり空間の任意の文字列と-pad。

また、スペースを使用printf '%4s'して左にパッドを(x)付けます。${(l:4:):-"($((++c)))"}代わりに使用できました。ただし、顕著な違いは、文字列が4文字を超える場合、文字列が${(l)}オーバーフローする一方で、文字列が切り捨てられることprintfです。


6

%s書式指定子は、(精度取ることができます%.20s例えば)を、そしてあなたが(と一定の精度に出力するfloat値をするときと同じように%.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。残念ながら、awk' printfはドットで埋めることはできず、スペースまたはゼロでのみ埋めることができるため、関数を作成する必要があります。

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 {}ブロック、ちょうど3つの配列、例えば、のいずれかにホスト名を挿入する/正規表現マッチ/のためにokfailunknown。または1つの連想配列(例:)hosts[hostname]="OK"。次に、行数をカウントし、それを使用して、行カウンターフィールドの幅を決定します。

また、不明なホスト(CONNECTION IMPOSSIBLE)と到達できないホスト(CONNECTION FAIL)を区別して出力することも決定しました。

sort -k3オプションであり、それによって、ちょうどグループの出力fping結果(「ホスト名が生きている」、「ホスト名が到達不能である」または「ホスト名:名前または知られていないサービス」)。がないsort場合、不明なホストは常に出力の最初に表示されます。ホスト名で並べ替えるsortことなく、単純なプレーン-k3

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.