방금 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
답변1
매개변수 확장을 사용하여 %-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
답변2
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 ${(r:25::string:)parameter}
또는옳은- 공백 대신 임의의 문자열로 채웁니다.
우리는 또한 printf '%4s'
사용합니다왼쪽- 공백으로 채웁니다 (x)
. 우리는 그것을 대신 사용할 수도 있었습니다 ${(l:4:):-"($((++c)))"}
. 그러나 한 가지 중요한 차이점은 문자열이 4자를 초과하면 ${(l)}
잘리고 오버플로가 발생한다는 것입니다 printf
.
답변3
형식 %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
답변4
fping
나는 and 로 할 것이다 awk
. 불행하게도 awk
' printf
는 점으로 채울 수 없고 공백이나 0으로만 채울 수 있으므로 다음과 같은 함수를 작성해야 했습니다.
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
.