How to Align the Columns of a Space Separated Table in Bash

How can I align the columns of a space separated table in Bash?

You might want the column command, usually with --table / -t to produce basic tabular output:

From the man page:

 -t, --table 

Determine the number of columns the input contains and create a table. Columns are delimited with whitespace, by default, or with the charac‐ters supplied using the --output-separator option. Table output is useful for pretty-printing.

column -t [file]

# or from stdin
cat file | column -t

# For a quick demonstration, format the output of mount
mount | column -t

column has a lot of other complex options. man column for details.

How can I align the columns of tables in Bash?

printf is great, but people forget about it.

$ for num in 1 10 100 1000 10000 100000 1000000; do printf "%10s %s\n" $num "foobar"; done
1 foobar
10 foobar
100 foobar
1000 foobar
10000 foobar
100000 foobar
1000000 foobar

$ for((i=0;i<array_size;i++));
do
printf "%10s %10d %10s" stringarray[$i] numberarray[$i] anotherfieldarray[%i]
done

Notice I used %10s for strings. %s is the important part. It tells it to use a string. The 10 in the middle says how many columns it is to be. %d is for numerics (digits).

See man 1 printf for more info.

How to clean up misaligned columns in text separated by spaces?

It's very ugly but this may work:

cat xx | ruby -nle 'puts $_.split().join("\t")' |pr --expand-tabs -tT

You may need to replace the single \t with multiple tab characters if your columns vary greatly in width.

This is ruby splitting the line on any white space, then joining using tabs. Finally pr is replacing tabs with spaces (and the -tT avoids the annoying headers and pagination)

If you know the fields are separated by a single character tr can do the replacement easily:

 cat xx | tr ' ' "\t"  |pr --expand-tabs -tT

Align columns in comma-separated file

Here's a portable way:

sed 's/,/:,/g' output.csv |
column -t -s: |
sed 's/ ,/,/g'

Explanation:

column -t aligns columns. The input separator can be specified with -s but the output separator is always a space (unless you have version like GNU or util-linux supporting the -o flag, see this answer.).

With column -s, -t output.csv the output would be just

"T_Hours" "T_Count" "T_Hours" ...
"00" "446" "00" ...
"01" "159" "01" ...
...

To keep the , in the output we have to pre- and post-process:

  • Use sed to insert an additional delimiter : in front of each comma-delimiter. The character you choose has to be a character that isn't otherwise in your input.
  • Use column -t specifying that : character as the delimiter. column will align all columns and replace all : by a space.
  • Use sed to delete the spaces (originally the : we inserted in the first command).
"T_Hours","T_Count","T_Hours",...
"00" ,"446" ,"00" ,...
"01" ,"159" ,"01" ,...
...

More info, see man column.

Replace tab with variable amount of spaces, maintaining the alignment

The POSIX utility pr called as pr -e -t does exactly what you want and AFAIK is present in every Unix installation.

$ cat file
ABC 1437 1 0 71 15.7 174.4
DEF 0 0 0 1 45.9 45.9
GHIJ 2 3 0 9 1.1 1.6

$ pr -e -t file
ABC 1437 1 0 71 15.7 174.4
DEF 0 0 0 1 45.9 45.9
GHIJ 2 3 0 9 1.1 1.6

and with the tabs visible as ^Is:

$ cat -ET file
ABC^I1437^I1^I0^I71^I15.7^I174.4$
DEF^I0^I0^I0^I1^I45.9^I45.9$
GHIJ^I2^I3^I0^I9^I1.1^I1.6$

$ pr -e -t file | cat -ET
ABC 1437 1 0 71 15.7 174.4$
DEF 0 0 0 1 45.9 45.9$
GHIJ 2 3 0 9 1.1 1.6$

Make a table out of array elements in Bash

Use printf for printing four elements per line, then align columns with column.

$ Var=(Title Album Song Rating 1 2 3 4 5 6 7 8 9 10 11 12)
$ printf '%s %s %s %s\n' "${Var[@]}" | column -t
Title Album Song Rating
1 2 3 4
5 6 7 8
9 10 11 12

You can also use a simple function to generate the format string for printf if the number of columns is dynamic.

genfmt() {
for ((i = 1; i < $1; i++)); do
printf '%%s '
done
printf '%%s\\n'
}

printf "$(genfmt 4)" "${Var[@]}" | column -t

Pretty print a space delimited file

Use awk so that you have tight control on how you want to format each field:

awk '{ printf("%-5s %-5s %-5s %s %s %s %s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) }' file

Produces:

5285  II-3  II-2  2 NA NA NA NA 40 NA NA c.211A>G
8988 III-3 III-4 1 NA NA NA NA NA NA NA c.211A>G
8F412 III-3 III-4 2 NA NA 28 NA NA NA NA c.211A>G
4H644 III-3 III-4 2 NA NA NA NA NA NA NA NA

Right Align Columns in Text File with Sed

You can use printf with width as you want like this:

awk '{printf "%-15s%3d%10s%2s%15s    %-5d\n", $1, $2, $3, $4, $5, $6}' file
apple 1 33.413 C cat 10
banana 2 21.564 B horse 356
cherry 3 43.223 D cow 32
pear 4 26.432 A goat 22
raspberry 5 72.639 C eagle 4
watermelon 6 54.436 A fox 976
pumpkin 7 42.654 B mouse 1
peanut 8 36.451 B dog 56
orange 9 57.333 C elephant 32
coconut 10 10.445 A frog 3
blueberry 11 46.435 B camel 446

Feel free to adjust widths to tweak the output.



Related Topics



Leave a reply



Submit