bash + özel biçimde yazdırmak için printf kullanma


12

Linux makineleri listesindeki ping erişimini kontrol etmek için aşağıdaki bash betiğini yazdım:

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

Bu yazdırır:

 (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

printfAşağıdaki formatı yazdırmak için bash komut dosyamda (veya başka bir komut) nasıl kullanabilirim ?

 (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)Nokta sayısını elde etmek için bir hesaplama yapabilirsiniz . Sonra printf '.%.s' {1..$DOTS}her döngü yinelemesinde kullanın . Böyle bir şey işe yarayacağını düşünüyorum.
coffeMug

Lütfen çözümünüzü cevap olarak açıklar
mısınız

Zaten bir cevabın var. ;-)
coffeMug

Yanıtlar:


19

%-sNoktalardan kaynaklanan boşlukları değiştirmek için parametre genişletmeyi kullanma :

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

WOW, kontrol edeyim ve yakında güncelleyeceğim ..........................
yael

1
Heh, akıllı! Birkaç bilgiçlik noktası: i) %2dparantez içine gereksiz bir boşluk ekliyor ($ list> = 10 olduğunda faydalı olabilir); ii) OP'nin kesin çıktısını almak için, ilkinden machine_indented=${machine_indented/../ .}önce fazladan boşluk eklemek isteyebilirsiniz .. Dediğim gibi bilgiçlik taslayan.
terdon

merhaba Choroba, lütfen cevabında terdon sözlerini düşünebilir misin?
yael

@yael: Çözümü ayarlamanız artık kolay olmalı :-)
choroba

BTW - neden & önce> / dev / null?
yael

8

for m in $listolduğu zshsözdizimi. İçinde basholurdu for i in "${list[@]}".

bashdolgu operatörleri yoktur. Doldurmayı printfrastgele karakterlerle değil, yalnızca boşluklarla yapabilirsiniz. zshdolgu operatörleri vardır.

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

Dolgu operatörüdür ${(r:25:)parameter}için doğru boşluklu veya uzunluğu 25 ile -pad ${(r:25::string:)parameter}için sağ yerine uzayın herhangi bir dize ile -pad.

Biz de kullanmak printf '%4s'için sol -pad (x)boşluklarla. Onun ${(l:4:):-"($((++c)))"}yerine kullanabilirdik. Dikkate değer bir fark, dize 4 karakterden daha uzunsa, ${(l)}taşması sırasında onu kesecek olmasıdır printf.


6

%sBiçim belirteci (bir hassasiyet alabilir %.20sörneğin) ve (ile çıkışa belirli bir hassasiyetle bir şamandıra değeri istediğinizde gibi %.4förneğin), çıkış en fazla olacak verilen dize argümanı birçok karaktere söyledi.

Makine adını ve noktaların bitmesi için yeterli noktayı içeren bir dize oluşturun:

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

Çıktı:

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

2

@ Choroba'nın cevabından çalınan şeyler ile:

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

Ben fpingve ile yapardım awk. Ne yazık ki, awk' printfnoktalar ile pad, sadece boşluk veya sıfır ile bu yüzden bir işlev yazmak zorunda:

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

Parantez içinde sıfır dolgulu 2 basamaklı sayılar kullanıyorum, böylece 10-99 ana bilgisayar $list(100+ yine de vidalayacak) varsa biçim vidalanmıyor . Alternatif, yazdırmayı bir END {}bloğa kadar ertelemek ve / regexp-match / ana makine adını üç diziden birine, örneğin ok, eklemek failgibi unknown. veya yalnızca bir ilişkilendirilebilir dizi (ör. hosts[hostname]="OK"). Daha sonra satır sayısını sayabilir ve bunu, satır sayacı alanının ne kadar geniş olması gerektiğine karar vermek için kullanabilirsiniz.

Ayrıca çıktı bilinmeyen ana bilgisayarlar ( CONNECTION IMPOSSIBLE) ve ulaşılamaz ana bilgisayarlar ( ) arasında ayrım yapmaya karar verdim CONNECTION FAIL.

Bu sort -k3isteğe bağlıdır, yalnızca fpingsonucu sonuca göre gruplandırır ("ana makine adı canlı", "ana makine adına erişilemiyor" veya "ana makine adı: Adı veya hizmeti bilinmiyor"). Olmadan, sortbilinmeyen ana bilgisayarlar her zaman çıktıda ilk görünür. Ana bilgisayar adına göre irade sortolmadan sadece düz -k3.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.