48

Sometimes, I'm getting as an input tab separated list, which is not quite aligned, for instance

var1  var2  var3
var_with_long_name_which_ruins_alignment  var2 var3

Is there an easy way to render them aligned?

var1                                      var2  var3
var_with_long_name_which_ruins_alignment  var2  var3
Elazar Leibovich
  • 3,231
  • 5
  • 27
  • 28

7 Answers7

64

So, the answer becomes:

column -t file_name

Note that this splits columns at any whitespace, not just tabs. If you want to split on tabs only, use:

column -t -s $'\t' -n file_name

The -s $'\t' sets the delimiter to tabs only and -n preserves empty columns (adjacent tabs).

P.S.: Just want to point out that the credit goes to Alex as well. The original hint was provided by him as a comment to the question, but was never posted as an answer.

Barun
  • 2,376
  • I'll wait a bit for Alex to get the credit, I think he deserves it. If he wouldn't answer in a few days I'll accept an answer from somebody else. – Elazar Leibovich Feb 20 '11 at 19:23
  • Sure! I too was unaware of column :) – Barun Feb 21 '11 at 05:51
  • 1
    This seems ideal but unfortunately column seems to fail when it encounters empty cells. See this post. Depending on which version of column you have, you may be able to specify the -n option to correct this. – John J. Camilleri Jul 18 '12 at 07:29
  • 2
    Also, this command will not only split on tabs, but also on "any whitespace". To split just on tabs, use column -t -s $'\t'. – Fritz Feb 06 '17 at 12:45
  • @Fritz why we have to use $? – Russell Teapot Dec 15 '20 at 05:34
  • 1
    The $ before a single quote ' expands escape sequences in the following string. In this case '\t' is a string of two characters: bachslash (ASCII 0x5C) followed by t (ASCII 0x74). But $'\t' contains only one character: a Tab (ASCII 0x09), because the escape sequence \t (which stands for "tab") is expanded to an actual tab character. You can try this using hexdump: Try echo -n '\t' | hd vs. echo -n $'\t' | hd. – Fritz Dec 15 '20 at 11:05
4

For manual tab stops: expand -t 42,48

For automatic tab stops, as suggested by alex: column -t

(expand is on all POSIX systems. column is a BSD utility, available in many Linux distributions as well, thanks to util-linux.)

2

Following on from Peter.O's comment which is what I wanted to align (tab delimited data, TSV), this phrase works very nicely:

column -t -s $'\t' /Users/me/data.csv | less --chop-long-lines
Sridhar Sarnobat
  • 1,802
  • 20
  • 27
2

Here's a script to do it:

aligntabs.pl

#!/usr/bin/perl

my $delim = '\s*\t\s*';

my %length = ();
my @lines = ();
for my $line (<>) {
    chomp $line;
    my @words = split $delim, $line;
    my $numwords = scalar(@words);
    for my $i (0..$numwords-1) {
        my $maxlen = $length{$i} // 0;
        my $thislen = length($words[$i]);
        $maxlen = ($thislen > $maxlen)? $thislen: $maxlen;
        $length{$i} = $maxlen;
    }
    push @lines, [@words];
}

foreach my $wordsref (@lines) {
    my @words = @$wordsref;
    my $numwords = scalar(@words);
    for my $i (0..$numwords-1) {
        if ($i < $numwords-1) {
            my $fieldlen = $length{$i};
            printf "%-${fieldlen}s ", $words[$i];
        }
        else {
            print $words[$i];
        }
    }
    print "\n";
}

usage

$ aligntabs.pl < infile
var1                                     var2 var3
var_with_long_name_which_ruins_alignment var2 var3
Mikel
  • 57,299
  • 15
  • 134
  • 153
1
sed 's/||/| |/g;s/||/| |/g' filename-here | column -s"|" -t | less -#2 -N -S

Explanation:

Sed will add a space between blank delimters

Column will add equal spacing between the columns

zydsld|asl|asd
das|aosdk|dd

becomes

zydsld|asl  |asd
das   |aosdk|dd 

Less will open the output in a file viewer. -N and -S will add line number and disable wrapping respectively

Rohit
  • 111
1

With Miller (http://johnkerl.org/miller/doc) you have pretty print output.

Run

mlr --inidx --ifs "\t" --opprint cat input | tail -n +2

to have

var1                                     var2 var3
var_with_long_name_which_ruins_alignment var2 var3
aborruso
  • 2,855
0

Using Miller (mlr) in a slightly different way from what's done in aborruso's answer:

$ mlr --t2p cat file
var1                                     var2 var3
var_with_long_name_which_ruins_alignment var2 var3

This reads the data as a TSV (tab-separated values) file, and simply outputs it in a pretty-printed table form. The --t2p option to mlr is short-hand for --itsv (input TSV) and --opprint (output pretty-printed) together.

With borders:

$ mlr --t2p --barred cat file
+------------------------------------------+------+------+
| var1                                     | var2 | var3 |
+------------------------------------------+------+------+
| var_with_long_name_which_ruins_alignment | var2 | var3 |
+------------------------------------------+------+------+

As a markdown table:

$ mlr --t2m cat file
var1 var2 var3
var_with_long_name_which_ruins_alignment var2 var3
Kusalananda
  • 333,661