Заполнение символов в printf - PullRequest
94 голосов
/ 10 декабря 2010

Я пишу скрипт оболочки bash для отображения, запущен процесс или нет.

Пока я получил это:

printf "%-50s %s\n" $PROC_NAME [UP]

Код дает мне такой вывод:

JBoss                                              [DOWN]

GlassFish                                          [UP]

verylongprocessname                                [UP]

Я хочу заполнить пробел между двумя полями с помощью '-' или '*', чтобы сделать его более читабельным. Как мне это сделать, не нарушая выравнивания полей?

Вывод, который я хочу получить:

JBoss -------------------------------------------  [DOWN]

GlassFish ---------------------------------------  [UP]

verylongprocessname -----------------------------  [UP]

Ответы [ 13 ]

67 голосов
/ 10 декабря 2010

Pure Bash, без внешних утилит

Эта демонстрация полностью оправдывает себя, но вы можете просто опустить вычитание длины второй строки, если вы хотите неровные линии справа.

pad=$(printf '%0.1s' "-"{1..60})
padlength=40
string2='bbbbbbb'
for string1 in a aa aaaa aaaaaaaa
do
     printf '%s' "$string1"
     printf '%*.*s' 0 $((padlength - ${#string1} - ${#string2} )) "$pad"
     printf '%s\n' "$string2"
     string2=${string2:1}
done

К сожалению, в этом методе длина строки пэда должна быть жестко задана, чтобы быть длиннее, чем самая длинная, которая, как вы думаете, вам понадобится, но длина пэда может быть переменной, как показано.Однако вы можете заменить первую строку этими тремя, чтобы иметь возможность использовать переменную для длины пэда:

padlimit=60
pad=$(printf '%*s' "$padlimit")
pad=${pad// /-}

Таким образом, пэд (padlimit и padlength) может быть основан наширина терминала ($COLUMNS) или рассчитывается по длине самой длинной строки данных.

Вывод:

a--------------------------------bbbbbbb
aa--------------------------------bbbbbb
aaaa-------------------------------bbbbb
aaaaaaaa----------------------------bbbb

Без вычитания длины второй строки:

a---------------------------------------bbbbbbb
aa--------------------------------------bbbbbb
aaaa------------------------------------bbbbb
aaaaaaaa--------------------------------bbbb

Первая строка может вместо этого быть эквивалентной (аналогично sprintf):

printf -v pad '%0.1s' "-"{1..60}

или аналогично для более динамичной техники:

printf -v pad '%*s' "$padlimit"

Вы можете выполнить печатьвсе на одной линии, если вы предпочитаете:

printf '%s%*.*s%s\n' "$string1" 0 $((padlength - ${#string1} - ${#string2} )) "$pad" "$string2"
61 голосов
/ 10 декабря 2010

Чистый Баш.Используйте длину значения 'PROC_NAME' в качестве смещения для фиксированной строки 'line':

line='----------------------------------------'
PROC_NAME='abc'
printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}"
PROC_NAME='abcdef'
printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}"

Это дает

abc ------------------------------------- [UP]
abcdef ---------------------------------- [UP]
14 голосов
/ 10 декабря 2010

Тривиальное (но работающее) решение:

echo -e "---------------------------- [UP]\r$PROC_NAME "
13 голосов
/ 26 октября 2015

Я думаю, что это самое простое решение. Встроенная оболочка, без встроенной математики. Он заимствует из предыдущих ответов.

Только подстроки и мета-переменная $ {# ...}.

A="[>---------------------<]";

# Strip excess padding from the right
#

B="A very long header"; echo "${A:0:-${#B}} $B"
B="shrt hdr"          ; echo "${A:0:-${#B}} $B"

Производит

[>----- A very long header
[>--------------- shrt hdr


# Strip excess padding from the left
#

B="A very long header"; echo "${A:${#B}} $B"
B="shrt hdr"          ; echo "${A:${#B}} $B"

Производит

-----<] A very long header
---------------<] shrt hdr
11 голосов
/ 10 декабря 2010

Нет способа дополнить что-либо, кроме пробелов, используя printf. Вы можете использовать sed:

printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'
8 голосов
/ 25 июля 2014
echo -n "$PROC_NAME $(printf '\055%.0s' {1..40})" | head -c 40 ; echo -n " [UP]"

Пояснение:

  • printf '\055%.0s' {1..40} - Создать 40 штрихов
    (тире интерпретируется как опция, поэтому вместо нее используйте экранированный код ascii)
  • "$PROC_NAME ..." - объединение $ PROC_NAME и тире
  • | head -c 40 - Обрезать строку до первых 40 символов
7 голосов
/ 07 мая 2015

Это еще проще и не требует внешних команд.

$ PROC_NAME="JBoss"
$ PROC_STATUS="UP"
$ printf "%-.20s [%s]\n" "${PROC_NAME}................................" "$PROC_STATUS"

JBoss............... [UP]
4 голосов
/ 24 июня 2014

с использованием echo только

Ответчик @Dennis Williamson работает просто отлично, за исключением того, что я пытался сделать это с помощью echo. Эхо позволяет выводить символы с определенным цветом. Использование printf удалит эту раскраску и напечатает нечитаемые символы. Вот альтернатива echo:

string1=abc
string2=123456
echo -en "$string1 "
for ((i=0; i< (25 - ${#string1}); i++)){ echo -n "-"; }
echo -e " $string2"

вывод:

abc ---------------------- 123456

Конечно, вы можете использовать все варианты, предложенные @Dennis Williamson, независимо от того, хотите ли вы, чтобы правая часть была выровнена по левому или правому краю (заменив 25 - ${#string1} на 25 - ${#string1} - ${#string2} и т. Д.

2 голосов
/ 24 мая 2014

Если вы заканчиваете символы пэда на некотором фиксированном номере столбца, то вы можете перебить и cut до длины:

# Previously defined:
# PROC_NAME
# PROC_STATUS

PAD="--------------------------------------------------"
LINE=$(printf "%s %s" "$PROC_NAME" "$PAD" | cut -c 1-${#PAD})
printf "%s %s\n" "$LINE" "$PROC_STATUS"
2 голосов
/ 10 декабря 2010

Вот еще один:

$ { echo JBoss DOWN; echo GlassFish UP; } | while read PROC STATUS; do echo -n "$PROC "; printf "%$((48-${#PROC}))s " | tr ' ' -; echo " [$STATUS]"; done
JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...