Как очистить столбцы с несогласованными в тексте?

У меня есть программа на C, которая выводит два столбца, совершенно несогласованных. Причиной несоосности является длина слов в первом столбце, очень разные.

У меня есть выходной файл, открытый в vi. Как быстро выровнять эти два столбца? Я в порядке с использованием awk, perl, sed, а не только инструментария vi (7.2). Кроме того, можем ли мы иметь общее решение для файлов с более чем двумя столбцами?

Вот пример файла

column1               column2
-------               -------
sdfsdfsddfsdfsdfsdfsd         343r5
dfgdfgdf             234
gdfgdfgdfgdfgf            645

Ответ 1

Предположительно, вы используете printf для вывода столбцов в первую очередь. Вы можете использовать дополнительные модификаторы в своей строке формата, чтобы убедиться, что все получилось.

  • Чтобы напечатать столбец определенной ширины (с выравниванием по правому краю), добавьте ширину перед флагом форматирования, например, "% 10s" напечатает столбец шириной 10. Если ваша строка длиннее 10 символов, столбец будет больше, чем вы хотите, поэтому выберите максимальное значение. Если строка короче, она будет дополнена пробелами.
  • Чтобы выравнивать по левому краю столбец, поставьте знак "впереди", например "% -10s". Мне нравится выравнивать строки и правильно выравнивать числа лично.
  • Если вы печатаете адреса, вы можете изменить символы заполнения от пробелов до нулей с нулевым значением: "% 010x".

Чтобы привести более подробный пример:

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]);

Это напечатает три столбца:

Name                            Address     Size
foo                            01234567      346
bar                            9abcdef0     1024
something-with-a-longer-name   0000abcd     2048

Ответ 2

Для быстрого и грязного исправления проведите его через столбец:

your_program | column -t

Если вам нужно включить пробелы в данные столбца, затем разделите поля на некоторый символ, например "|" и:

your_program | column -t -s "|"

Вы можете использовать любой символ для разделителя и указать его с помощью ключа -s. Управляющие символы возможны, но немного сложнее работать.

Но, как сказал Джей, вам лучше исправить вашу программу, чтобы правильно отформатировать результат.

Ответ 3

Здесь awk-решение: c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'

Ответ 4

Если вы хотите выполнить обработку в Vim (в отличие от фиксации генератора), установите superb align plugin и выполните следующие действия:

ggVG
\tsp

Первая команда разбивается на gg (перейдите к началу файла), V (введите режим визуальной линии), G (перейдите в конец файла). В качестве комбинации он визуально выбирает весь файл. \tsp - это выравнивающая карта, которая выравнивается по белому пространству.

Если вы предпочитаете делать что-то в командной строке :, вы можете использовать альтернативный разделитель (например, ###) и использовать строку командной строки Align:

:%s/\s\+/###/g
:%Align ###
:%s/### //g

Это длиннее, но вы можете найти его более логичным/запоминающимся.

Ответ 5

Я написал небольшую программу, которая решает эту проблему с помощью Perl. Он также работает для нескольких столбцов.

#!/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, @$_;
}

Ответ 6

Я просто добавляю отсутствующие в других вариантах ответов:

Emacs с Mx align-regexp, Mx align-string и т.д. подробнее на http://www.emacswiki.org/emacs/AlignCommands

Командная оболочка POSIX (возможно, встроенная) printf:

while read f1 f2 f3 tail; do printf "%10s %5s | %s" $f1 $f3 $tail; done <file.txt