5

I was recently surprised to find out, that the POSIX list of utilities doesn't include the column utility. column first appeared way back in 4.3BSD, and it's is pretty useful. Is there a POSIX equivalent of it?


The exact command I would like to replace is:

$ more -- ./tmp.txt 
1   SMALL   000a
2   VERY_VERY_VERY_VERY_LONG    000b
3   SMALL   000c
$ column -t -- ./tmp.txt 
1  SMALL                     000a
2  VERY_VERY_VERY_VERY_LONG  000b
3  SMALL                     000c
$

That is, expand tabs to create prettier columns.

5

POSIX prefers to codify existing behavior, and to only mandate new features or features that are not widely adopted when the existing behavior is unsatisfactory. Nowadays there isn't much call for presentation of data using unformatted text in fixed-width fonts, so column is unlikely to become mandatory. Unlike pr, it's from BSD, it isn't present System V and other historical unices, so it isn't grandfathered in.

Like any other text utility, you can express it in awk with a moderate amount of work. Here's a minimally tested implementation of column -t. Awk's -v option is similar to column's -s in simple cases (with a single character).

#!/usr/bin/env awk
{
    if (max_column < NF) max_column = NF;
    for (i = 1; i <= NF; i++) {
        if (width[i] < length($i)) width[i] = length($i);
        data[NR, i] = $i;
    }
}
END {
    for (i = 1; i < max_column; i++) format[i] = sprintf("%%-%ds  ", width[i]);
    format[max_column] = "%s\n";
    for (k = 1; k <= NR; k++) {
        for (i = 1; i <= max_column; i++) printf format[i], data[k, i];
    }
}
| improve this answer | |
  • Thanks, this works! Although I will probably replace the double space in sprintf with a tab, so that fullwidth characters (like the Han characters or emoji) don't screw up the alignment. – Ainar-G Aug 2 at 17:22
  • Gilles, will this also work if you use standard awk array[index1 SUBSEP index2] expressions instead of arrays of arrays? – Mark Plotnick Aug 2 at 17:30
  • @MarkPlotnick Sure. I'd forgotten that was a gawk extension, thanks. – Gilles 'SO- stop being evil' Aug 2 at 17:57
4

pr does a lot of what column does. If you specify an actual command line we can work on the replacement one.

NAME pr - convert text files for printing

SYNOPSIS pr [OPTION]... [FILE]...

DESCRIPTION Paginate or columnate FILE(s) for printing.

For your particular case, you could use awk:

awk '{printf("%2s %30s %10s", $1, $2, $3);}' file.txt

Note that the width specifiers 2, 30 and 10 are hardcoded, you have to choose the values for your input, or read the file twice (once to get the maximum widths for each column and the second time to print it out with the values you got).

| improve this answer | |
  • Thanks, I added more info. I want a replacement for column -t. – Ainar-G Aug 2 at 16:40
3

As far as I know there is no direct equivalent to column among the POSIX set of utilities.

A possible (cheap) POSIX solution could be:

$ tr -s ' ' '\n' <<"EOT" | pr -3 -a -t
1   SMALL   000a
2   VERY_VERY_VERY_VERY_LONG    000b
3   SMALL   000c
EOT
1                       SMALL                   000a
2                       VERY_VERY_VERY_VERY_LON 000b
3                       SMALL                   000

After copying/pasting it, your sample data had fields separated by spaces. In case they were actually separated by a single TAB, you can use tr '\t' '\n'.

Of course this assumes that all the input lines have the same number of fields. The rather evident downside is that columns are evenly sized, which make them look significantly less nice than the output of column -t.

Also, as shown in the above sample, pr uses a fixed length for lines (defaulting to 72 characters), and truncates fields that don't fit into their column's width. It may be then necessary to explicitly set the page width (-w) to a suitable value.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.