Padding characters in printf

2019-01-10 01:03发布

I am writing a bash shell script to display if a process is running or not.

So far, I got this:

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

The code gives me this output:

JBoss                                              [DOWN]

GlassFish                                          [UP]

verylongprocessname                                [UP]

I want to pad the gap between the two fields with a '-' or '*' to make it more readable. How do I do that without disturbing the alignment of the fields?

The output I want is:

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

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

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

12条回答
叛逆
2楼-- · 2019-01-10 01:09

There's no way to pad with anything but spaces using printf. You can use sed:

printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'
查看更多
干净又极端
3楼-- · 2019-01-10 01:09

using echo only

The anwser of @Dennis Williamson is working just fine except I was trying to do this using echo. Echo allows to output charcacters with a certain color. Using printf would remove that coloring and print unreadable characters. Here's the echo-only alternative:

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

output:

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

of course you can use all the variations proposed by @Dennis Williamson whether you want the right part to be left- or right-aligned (replacing 25 - ${#string1} by 25 - ${#string1} - ${#string2} etc...

查看更多
何必那么认真
4楼-- · 2019-01-10 01:11

Here's another one:

$ { 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]
查看更多
小情绪 Triste *
5楼-- · 2019-01-10 01:14

I think this is the simplest solution. Pure shell builtins, no inline math. It borrows from previous answers.

Just substrings and the ${#...} meta-variable.

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"

Produces

[>----- 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"

Produces

-----<] A very long header
---------------<] shrt hdr
查看更多
混吃等死
6楼-- · 2019-01-10 01:15

If you are ending the pad characters at some fixed column number, then you can overpad and cut to length:

# 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"
查看更多
Ridiculous、
7楼-- · 2019-01-10 01:15

Bash + seq to allow parameter expansion

Similar to @Dennis Williamson answer, but if seq is available, the length of the pad string need not be hardcoded. The following code allows for passing a variable to the script as a positional parameter:

COLUMNS="${COLUMNS:=80}"
padlength="${1:-$COLUMNS}"
pad=$(printf '\x2D%.0s' $(seq "$padlength") )

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

The ASCII code "2D" is used instead of the character "-" to avoid the shell interpreting it as a command flag. Another option is "3D" to use "=".

In absence of any padlength passed as an argument, the code above defaults to the 80 character standard terminal width.

To take advantage of the the bash shell variable COLUMNS (i.e., the width of the current terminal), the environment variable would need to be available to the script. One way is to source all the environment variables by executing the script preceded by . ("dot" command), like this:

. /path/to/script

or (better) explicitly pass the COLUMNS variable when executing, like this:

/path/to/script $COLUMNS
查看更多
登录 后发表回答