Как убрать смещенные столбцы в тексте? - PullRequest
25 голосов
/ 01 октября 2009

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

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

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

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

Ответы [ 6 ]

35 голосов
/ 06 ноября 2011

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

your_program | column -t

Если вам необходимо включить пробелы в данные столбца, разделите поля символом, например «|» и:

your_program | column -t -s "|"

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

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

29 голосов
/ 01 октября 2009

Предположительно, вы используете 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
9 голосов
/ 01 октября 2009

Вот решение awk: c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'

4 голосов
/ 02 октября 2009

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

ggVG
\tsp

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

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

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

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

2 голосов
/ 31 июля 2013

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

Emacs с M-x align-regexp , M-x 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
2 голосов
/ 01 октября 2009

Я написал небольшую программу, которая решает эту проблему с помощью 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, @$_;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...