When trying to format printf
output involving strings containing multi-byte characters, it became clear that printf
does not count literal characters but the number of bytes, which makes formatting text difficult if single-byte and multi-byte characters are mixed. For example:
$ cat script
#!/bin/bash
declare -a a b
a+=("0")
a+=("00")
a+=("000")
a+=("0000")
a+=("00000")
b+=("0")
b+=("├─00")
b+=("├─000")
b+=("├─0000")
b+=("└─00000")
printf "%-15s|\n" "${a[@]}" "${b[@]}"
$ ./script
0 |
00 |
000 |
0000 |
00000 |
0 |
├─00 |
├─000 |
├─0000 |
└─00000 |
I found various suggested work-arounds (mainly wrappers using another language or utility to print the text). Are there any native bash solutions? None of the documented printf
format strings appear to help. Would the locale
settings be relevant in this situation, e.g., to use a fixed-width character encoding like UTF-32?
zsh
orfish
where that was fixed, or use ksh93'sprintf '%-15Ls'
or use expand or some of the other solutions at Why is printf "shrinking" umlaut? which looks like a duplicate to me. – Stéphane Chazelas Nov 26 '17 at 21:16printf
respect bytes rather than characters, the answer to this question appears to be "no" if one wants to be able to print both to a terminal and to a file. – user001 Nov 26 '17 at 22:02bash
is a command line interpreter, you can invoke any command withinbash
likezsh -c 'printf "$@"' zsh "%-15s|\n" "${a[@]}" "${b[@]}"
for instance, or any of the commands mentioned there to align text. native solution makes little sense for a tool that is designed to run other tools. You could implement a solution in bash that doesn't invoke non-builtin utilities, but that's not how you do things in shells. – Stéphane Chazelas Nov 26 '17 at 22:21