bash + с помощью printf для печати в специальном формате

Я просто написал следующий скрипт bash для проверки доступа ping в списке Linux-машин

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 

5 Solutions collect form web for “bash + с помощью printf для печати в специальном формате”

Использование расширения параметра для замены пробелов, полученных из %-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 , #!/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 

for m in $list – синтаксис zsh . В bash это будет for i in "${list[@]}" .

bash не имеет операторов заполнения. Вы можете делать дополнения с помощью printf но только с пробелами, а не с произвольными символами. zsh имеет 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 - #! /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} 🙂 ${(r:25:)parameter} на правую панель с длиной 25 с пробелами или параметр ${(r:25::string:)parameter} 🙂 ${(r:25::string:)parameter} на правую панель с любой строкой вместо пробела.

Мы также используем printf '%4s' влево- pad (x) с пробелами. Мы могли бы использовать ${(l:4:):-"($((++c)))"} . Заметная разница состоит в том, что если длина строки больше 4 символов, ${(l)} усекает ее, а она будет переполняться с помощью printf .

Спецификатор формата %s может принимать точность (например, %.20s ) и так же, как если вы хотите вывести значение с плавающей точкой в ​​определенную точность (например, с %.4f ), вывод будет не более, чем для многих символов из заданного аргумента строки.

Поэтому создайте строку, содержащую имя машины и достаточное количество точек, чтобы выровнять точки:

 C=0 for M in vboxhost ntp.stupi.se example.com nonexistant; do if ping -q -c 1 "$M" >/dev/null 2>&1; then OK="OK" else OK="FAIL" fi printf "(%d) %.20s CONNECTION %s\n" \ $(( ++C )) "${M} ...................." $OK done 

Вывод:

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

С материалами, украденными от ответа @ 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 , #!/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 

Я бы сделал это с fping и awk . К сожалению, printf awk не может набирать точки, только с пробелами или нулями, поэтому мне нужно написать функцию:

 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 

Я использую в круглых скобках двузначные числа с нулевым запасом, чтобы формат не зависал, если в $list 1099 есть 10-99 хостов (100+ все равно его испортит). Альтернативой было бы отложить печать до блока END {} , а для / regexp-matches / просто вставить имя хоста в один из трех массивов, например, ok , fail , unknown . или только один ассоциативный массив (например, hosts[hostname]="OK" ). Затем вы можете подсчитать количество строк и использовать это, чтобы определить, насколько широким будет поле счетчика.

Я также решил, что выходные данные отличаются между неизвестными хостами ( CONNECTION IMPOSSIBLE ) и недоступными хостами ( CONNECTION FAIL ).

sort -k3 является обязательным, он просто группирует вывод по результату fping («hostname is alive», «hostname isreachable» или «имя хоста: имя или услуга неизвестна»). Без sort неизвестные хосты всегда будут отображаться сначала на выходе. Просто sort без -k3 будет сортироваться по имени хоста.

  • Почему Firefox не может открыть ссылку со сценарием оболочки, который использует `source`?
  • Как прочитать файл свойств в ассоциативный массив?
  • изменение идентификатора владельца UID для 10 пользователей в каталоге 10 + TB
  • как отображать файл ввода / вывода на оболочке
  • Как проверить скрипт оболочки, если исполняемый файл запущен или нет?
  • Что я должен рассмотреть, чтобы написать сценарий, который реагирует на нажатие клавиши?
  • Возврат только содержимого до и после номера строки с разными совпадающими словами
  • как передать смесь аргументов в скрипт и только из них необязательный -аргумент
  • Проверить успешность команды в bash
  • Отрицательные аргументы для головы / хвоста
  • sed с множественным выражением для аргумента на месте
  • Linux и Unix - лучшая ОС в мире.