I have a function in a bash script: message_offset
which is used to print the status of a bash script.
i.e. you would call it passing a message into it and a status, like this
message_offset "install font library" "[ OK ]"
and it would print into the terminal where printf
's %*s
format is used to always set the rightmost character of [ OK ]
at 80 columns wide
e.g. output would be
install font library [ OK ]
update configuration file on server [ ERR ]
^
|
always
at 80
If echo
was used output would look like this
install font library [ OK ]
update configuration file on server [ ERR ]
code:
#!/usr/bin/env bash
function message_offset() {
local message="$1"
local status="$2"
# compensate for the message length by reducing the offset
# by the length of the message,
(( offset = 80 - ${#message} ))
# add a $(tput sgr0) to the end to "exit attributes" whether a color was
# set or not
printf "%s%*s%s" "${message}" 80 "$status" "$(tput sgr0)"
}
this all works ok, until I try to use tput
to add some color sequences into the string, i.e. to make "[ ERR ]" red.
It seems that the printf "%*s"
formatting is counting
the tput character sequences when its setting the offset, so if I call the function like this
message_offset "update configuration file on server" "$(tput setaf 1)[ ERR ]"
the output will look something like:
install font library [ OK ]
update configuration file on server [ ERR ]
because printf "%*s"
is saying hey this string has got all the "[ ERR ]"
characters, plus the "$(tput setaf 1)
chars, but obviously the "$(tput setaf 1)
chars are not printed, so don't actually affect the padding.
Is there a way I can add color the "status" messages, and also use the tput
style color sequences?
Best Answer
You're making this a lot more complicated than it should be. You can handle alignment with
$message
and not care about the width of ANSI sequences:Edit: Please note that most
printf(1)
implementations don't cope well with lengths calculations for multibyte charsets. So if you want to print messages with accented characters in UTF-8 you might need a different approach. shrug