I have a C program that outputs two columns, utterly misaligned. The reason for the misalignment is lengths of words in the first column are very different.
I have an o
I wrote a small program that solves this problem using Perl. It also works for multiple columns.
#!/usr/bin/perl
use strict;
use warnings;
my $sep = 2;
sub max {
my ($a,$b) = @_;
return $a > $b ? $a : $b;
}
my @rows;
my $cols;
my $max = 0;
while (<>) {
next if m/^\s*$/;
my (@cols) = split m'\s+';
for (@cols) {
$max = max($max, length);
}
$cols = @cols;
push @rows, \@cols;
}
for (@rows) {
my $str = join '', (('%-' . ($max+$sep) . 's') x $cols);
$str .= "\n";
printf $str, @$_;
}
Here's a awk solution : c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'
Presumably you are using printf
to output the columns in the first place. You can use extra modifiers in your format string to make sure things get aligned.
To give a more in depth example:
printf("%-30s %8s %8s\n", "Name", "Address", "Size");
for (i = 0; i < length; ++i) {
printf("%-30s %08x %8d\n", names[i], addresses[i], sizes[i]);
This would print three columns like this:
Name Address Size
foo 01234567 346
bar 9abcdef0 1024
something-with-a-longer-name 0000abcd 2048
For a quick-and-dirty fix, pipe it through column:
your_program | column -t
If you need to include spaces in the column data, then delimit the fields with some character such as "|" and:
your_program | column -t -s "|"
You can use any character for a delimiter and specify it with the -s switch. Control characters are possible but a little trickier to work with.
But as Jay mentioned you're better off fixing your program to format the output properly.
I just add missing in another answers options:
Emacs with M-x align-regexp, M-x align-string, etc. read more at http://www.emacswiki.org/emacs/AlignCommands
POSIX shell (possibly build-in) command printf:
while read f1 f2 f3 tail; do printf "%10s %5s | %s" $f1 $f3 $tail; done <file.txt
If you want to do the processing in Vim (as opposed to fixing the generator), install the superb align plugin and run the following:
ggVG
\tsp
The first command breaks down to gg
(go to the start of the file), V
(enter visual line mode), G
(go to the end of the file). As a combination, it visually-selects the entire file. \tsp
is an Align map that aligns on white-space.
If you prefer to do things at the :
command line, you can use an alternative separator (e.g. ###
) and use the command-line Align:
:%s/\s\+/###/g
:%Align ###
:%s/### //g
It's longer, but you may find it more logical/memorable.