Home > Blockchain >  Printing and padding strings with bash/printf
Printing and padding strings with bash/printf

Time:09-16

In bash scripts I like to use printf "%-20s" "some string" to create columns that line up. That works great with regular text, but not really for multi-byte unicode, nor if using any kind of terminal decoration.

Works great:

for i in string longer_string Some_kind_of_monstrosity ; do
   printf "%-20s" $i ; echo " OK"
done

Everything is reasonably well lined up:

string               OK
longer_string        OK
Some_kind_of_monstrosity OK

However - it doesn't work very well with multi-byte unicode or colour codes:

printred () { tput setaf 1; printf %b "$*"; tput sgr0; }
printf "%-20s" test             ; echo " NOK"
printf "%-20s" $(printred RED)  ; echo " NOK"
printf "%-20s" "★★★★"         ; echo " NOK"

It looks like both the bash builtin printf and the coreutils/printf simply count the number of bytes in the string, rather than how many character that will be visible on the output:

test                 NOK
RED       NOK
★★★★         NOK

Is there a way to achieve this nicely in bash? (I'm using bash 5.0.17, but I'm not averse to using some other tool.)

CodePudding user response:

simple command column meets your need.

column -t < input.txt

CodePudding user response:

The %-20s is just blindly counting bytes and it does not understand ANSI control sequences so you can ask it to count only the text part.

Example:

RESET=$( tput sgr0 )
RED=$( tput setaf 1 )

printf '%-20s OK?\n' foobar
printf '%s%-20s%s OK?\n' "$RED" foobar "$RESET"

enter image description here

  • Related