How can I clean up misaligned columns in text?

前端 未结 6 661
佛祖请我去吃肉
佛祖请我去吃肉 2021-01-31 09:08

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

相关标签:
6条回答
  • 2021-01-31 09:39

    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, @$_;
    }
    
    0 讨论(0)
  • 2021-01-31 09:43

    Here's a awk solution : c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'

    0 讨论(0)
  • 2021-01-31 09:53

    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 print a column of a specific width (right-justified), add the width before the formatting flag, e.g., "%10s" will print a column of width 10. If your string is longer than 10 characters, the column will be longer than you want, so choose a maximum value. If the string is shorter, it will be padded with spaces.
    • To left-justify a column, put a - sign in front, e.g., "%-10s". I like to left-justify strings and right-justify numbers, personally.
    • If you are printing addresses, you can change the fill characters from spaces to zeroes with a leading zero: "%010x".

    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
    
    0 讨论(0)
  • 2021-01-31 09:57

    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.

    0 讨论(0)
  • 2021-01-31 09:59

    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
    
    0 讨论(0)
  • 2021-01-31 10:00

    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.

    0 讨论(0)
提交回复
热议问题