adamsfamily
adamsfamily

Reputation: 1974

bash - How to align text with printf into columns with non-ascii characters?

How can I make printf to align values into columns even with non-ascii characters?

The following commands should align values in the 2nd and 3rd paramter to fixed 20-character width:

printf "%-20s %-20s\n" "Foo" "Bar"
printf "%-20s %-20s\n" "Fooo" "Bar"
printf "%-20s %-20s\n" "Foooó" "Bar"
printf "%-20s %-20s\n" "Foooóó" "Bar"

I would expect the following to be printed:

Foo                  Bar
Fooo                 Bar
Foooó                Bar
Foooóó               Bar

In reality, this gets printed:

Foo                  Bar
Fooo                 Bar
Foooó               Bar
Foooóó             Bar

For some reason any non-ascii character (such as ó in my example) shortens the column by 1 character.

Upvotes: 3

Views: 1547

Answers (2)

anubhava
anubhava

Reputation: 785058

Non-ascii character e.g. ó is not printed like ASCII that are single width characters.

One solution is to use tab character in between 2 strings in printf and pipe output to column:

prnt() {
    printf "%-20s\t%-20s\n" "Foo" "Bar"
    printf "%-20s\t%-20s\n" "Fooo" "Bar"
    printf "%-20s\t%-20s\n" "Foooo" "Bar"
    printf "%-20s\t%-20s\n" "Fooooo" "Bar"
    printf "%-20s\t%-20s\n" "Foooooo" "Bar"
    printf "%-20s\t%-20s\n" "Fooooooo" "Bar"
    printf "%-20s\t%-20s\n" "Foooooooo" "Bar"
    printf "%-20s\t%-20s\n" "Fooooooooo" "Bar"
    printf "%-20s\t%-20s\n" "Foooooooooo" "Bar"
    printf "%-20s\t%-20s\n" "Fóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóóóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóóóóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóóóóóóó" "Bar"
    printf "%-20s\t%-20s\n" "Fóóóóóóóóóó" "Bar"
}
 
prnt | column -t -s $'\t'

Online Demo

Output:

Foo                   Bar                 
Fooo                  Bar                 
Foooo                 Bar                 
Fooooo                Bar                 
Foooooo               Bar                 
Fooooooo              Bar                 
Foooooooo             Bar                 
Fooooooooo            Bar                 
Foooooooooo           Bar                 
Fóó                   Bar                 
Fóóó                  Bar                 
Fóóóó                 Bar                 
Fóóóóó                Bar                 
Fóóóóóó               Bar                 
Fóóóóóóó              Bar                 
Fóóóóóóóó             Bar                 
Fóóóóóóóóó            Bar                 
Fóóóóóóóóóó           Bar                 

Upvotes: 1

John1024
John1024

Reputation: 113834

Another solution is to use awk. Awk's printf appears to understand unicode better than bash's printf. Try:

$ cat script.sh
#!/bin/sh
awk 'BEGIN{
printf "%-20s %-20s\n", "Foo", "Bar"
printf "%-20s %-20s\n", "Fooo", "Bar"
printf "%-20s %-20s\n", "Foooó", "Bar"
printf "%-20s %-20s\n", "Foooóó", "Bar"
}'

When run, this produces columns that line up:

$ sh script.sh
Foo                  Bar                 
Fooo                 Bar                 
Foooó                Bar                 
Foooóó               Bar       

Upvotes: 0

Related Questions