Note that in bash, printf's %-63.63s pads with spaces and truncates to 63 bytes not characters, so can't be used for formatting / aligning unless all characters are single byte. 99.99% of characters are encoded on more than one byte in UTF-8. Your U+2263 character is encoded on 3 bytes in UTF-8, 4 bytes in GB18030.
bash's ${var:offset:length}, like ksh93's where it copied it from works at character level, but even then that only works if all characters are single-width.
To align text properly, possible approaches are to:
- use padding/truncation operators that take into account the display width of characters.
- assuming the output goes to a terminal, use control sequences to tell the terminal to write what you want at the write place and erase what you don't want.
For 1, you could use a shell such as ksh93 or zsh that has builtin operators for that instead of bash.
In zsh:
align() printf ' \u2263 %s \u2263\n' ${(j[ ]mr[63])@}
The r[length] parameter expansion flag (here short for r[length][ ] as space is the default padding characters) right pads to the given length, and with m, that length is in terms of display width.
Or to left-align (and right-pad) $1 and right-align $2, as you later clarified:
align() printf ' \u2263 %s \u2263\n' "${(mr[31])1} ${(ml[31])2}"
With ksh93, it's even simpler:
align() printf ' \u2263 %-63.63Ls \u2263\n' "$1 $2"
Where %Ls as opposed to %s takes a string of characters, not bytes and pads and truncates based on their display width.
Or to left-align $1 and right-align $2:
align() printf ' \u2263 %-31.31Ls %31.31Ls \u2263\n' "$1" "$2"
Note that those don't work if the input contains control characters.
For 2, you could: disable auto-margins, write the whole text, move to column 68 and write " ≣" and erase the rest:
am_off=$(tput rmam) am_on=$(tput smam)
col68=$(tput cr; tput cuf 68)
del_to_eol=$(tput el)
align() {
printf ' \u2263 %s\u2263%s\n' "$am_off$1 $2$col68 " "$del_to_eol$am_on"
}