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 ^I
s:
$ 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
How to Capture All of My Compiler's Output to a File
Iterate Over Lines Instead of Words in a for Loop of Shell Script
Move Files to Directories Based on Extension
Unshare --Pid /Bin/Bash - Fork Cannot Allocate Memory
Finding Dlls Required of a Win Exe on Linux (Cross-Compiled with Mingw)
Does The Bios Copy The 512-Byte Bootloader to 0X7C00
Fast String Search in a Very Large File
In Linux Terminal, How to Delete All Files in a Directory Except One or Two
How to Debug a Futex Contention Shown in Strace
How to File Split at a Line Number
How to Upgrade Openssl in Centos 6.5/Linux/Unix from Source
Changing Location of Core Dump
Examining C/C++ Heap Memory Statistics in Gdb
How to Set a Global Nofile Limit to Avoid "Many Open Files" Error
How to Execute Script in The Current Shell on Linux