2009-10-01 10 views
23

Mam program C, który wyprowadza dwie kolumny, całkowicie źle wyrównane. Przyczyną niewspółosiowości są długości słów w pierwszej kolumnie są bardzo różne.Jak mogę usunąć źle ustawione kolumny w tekście?

Mam plik wyjściowy otwarty w vi. Jak szybko wyrównać te dwie kolumny? Nie mam problemu z używaniem zestawu narzędzi awk, perl, sed, a nie tylko vi (7.2). Czy możemy mieć ogólne rozwiązanie dla plików z więcej niż dwiema kolumnami?

Oto przykładowy plik

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

Odpowiedz

26

Prawdopodobnie używasz printf do wyjścia kolumny w pierwszej kolejności. Możesz użyć dodatkowych modyfikatorów w ciągu znaków, aby upewnić się, że wszystko jest wyrównane.

  • Aby wydrukować kolumny określonej szerokości (z wyrównaniem do prawej), dodać szerokość przed flagą formatowania, np: „% 10s” będzie drukować kolumnę szerokości 10. Jeśli łańcuch jest dłuższy niż 10 znaków , kolumna będzie dłuższa niż chcesz, więc wybierz maksymalną wartość. Jeśli ciąg jest krótszy, zostanie uzupełniony spacjami.
  • Aby po lewej stronie - uzasadnić kolumnę, umieść znak - z przodu, np. "% -10s". Lubię lewicowo-usprawiedliwiać ciągi i poprawiać numery osobiście.
  • Jeśli drukujesz adresy, możesz zmienić znaki wypełnienia z spacji na zera z wiodącym zerem: "% 010x".

dać więcej w przykładzie głębokość:

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

Byłoby to wydrukować trzy kolumny tak:

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

Oto rozwiązanie awk: c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'

2

Napisałem mały program rozwiązujący ten problem za pomocą Perla. Działa również dla wielu kolumn.

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

Jeśli chcesz zrobić przetwarzanie w vim (w przeciwieństwie do mocowania generatora), zainstalować doskonałąalign plugin i uruchom następujące:

ggVG 
\tsp 

Pierwsze przerw dowodzenia do gg (przejdź do początku pliku), V (wprowadź tryb linii wizualnej), G (przejdź do końca pliku). Jako kombinację wizualnie wybiera cały plik. \tsp to mapa wyrównaj, która wyrównuje białe znaki.

Jeśli wolisz robić rzeczy w wierszu poleceń :, można użyć alternatywnego separator (np ###) i korzystać z wiersza polecenia align:

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

To dłużej, ale można go znaleźć więcej logiczne/niezapomniane.

33

Dla szybkiego i brzydka fix, rura go przez kolumnę:

your_program | column -t 

Jeśli chcesz zawierać spacji w danych kolumny, a następnie wyznaczają pola z charakterem takich jak „|” i:

your_program | column -t -s "|" 

Możesz użyć dowolnego znaku separatora i określić go za pomocą przełącznika -s. Znaki kontrolne są możliwe, ale nieco trudniejsze w obsłudze.

Ale jak wspomniał Jay, lepiej jest poprawić program, aby poprawnie sformatować dane wyjściowe.

+0

można użyć funkcji bash, aby łatwo określić znaki sterujące, na przykład zakładka: 'column -t -s $ '\ t'' –

+0

Ostrzeżenie: kolumna nie lubi linii, które są" zbyt długie ", a podczas gdy' man column' wskazuje ograniczenie na 2048 bajtów, w praktyce wystarcza kilkaset bajtów, aby dusić (przynajmniej na Debianie 8.3). –

2

Dodam tylko brakuje w kolejnych opcji odpowiedzi:

Emacs Mx align-regexp, Mx align-strunowej, itd. Czytaj więcej na http://www.emacswiki.org/emacs/AlignCommands

powłoki POSIX (ewentualnie wbudowany) komenda printf:

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