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?
zshorfishwhere 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:16printfrespect 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:02bashis a command line interpreter, you can invoke any command withinbashlikezsh -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