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

해결책으로 답변
해주십시오

이미 답변이 있습니다. ;-)
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

와우, 내가 확인하자 곧 업데이트 할 것입니다 ..........................
yael

1
으악! 몇 가지 논점 : i) %2d괄호 안에 불필요한 공간을 추가하고있다 ($ list> = 10 일 때 유용 할 수 있지만); ii) OP의 정확한 출력 을 얻으 려면 machine_indented=${machine_indented/../ .}첫 번째 앞에 추가 공간 을 추가 하기 위해 추가 할 수 있습니다 .. 내가 말했듯이, pedantic.
terdon

안녕 Choroba, 당신은 당신의 대답에 terdon 말을 고려할 수 있습니까?
yael

@ yael : 솔루션을 조정하는 것이
쉬워야

BTW-왜> / dev / null 앞에 &를 추가해야합니까?
yael

8

for m in $listzsh구. 에 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예를 들어)을, 그리고 당신 (과 출력에 특정 정밀도 부동 소수점 값을 할 때처럼 %.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

나는 그것을 할 거라고 fping하고 awk. 불행하게도, 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

10-99 개의 호스트가있는 경우 형식이 고정되지 않도록 괄호 안에 0으로 채워진 2 자리 숫자를 사용하고 있습니다 $list(100 +는 여전히 실수입니다 ). 대안은 END {}블록 까지 인쇄를 지연 시키고 / regexp-matches /가 호스트 이름을 세 개의 배열 중 하나에 삽입하는 것입니다 (예 : ok, fail) unknown. 또는 하나의 연관 배열 (예 :) hosts[hostname]="OK". 그런 다음 라인 수를 세고이를 사용하여 라인 카운터 필드의 너비를 결정할 수 있습니다.

또한 출력을 알 수없는 호스트 ( CONNECTION IMPOSSIBLE)와 연결할 수 없는 호스트 ( )를 구별하기로 결정했습니다 CONNECTION FAIL.

(가) sort -k3선택 사항이며, 바이 그것은 단지 그룹의 출력 fping결과 ( "호스트 이름이 살아있다", "호스트에 연결할 수"또는 "호스트 이름 : 이름이나 알 수없는 서비스"). 이 없으면 sort알 수없는 호스트가 항상 출력에서 ​​첫 번째로 나타납니다. 의지 sort없이 평범한 -k3호스트 이름으로 정렬합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.