2009-10-01 16 views
23

Ho un programma C che emette due colonne, completamente disallineate. La ragione del disallineamento è la lunghezza delle parole nella prima colonna sono molto diverse.Come posso cancellare colonne disallineate nel testo?

Ho un file di output aperto in vi. Come allineare rapidamente queste due colonne? Sto bene con l'uso di set di strumenti awk, perl, sed, e non solo di vi (7.2). Inoltre, possiamo avere una soluzione generica per i file con più di due colonne?

Ecco file di esempio

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

risposta

26

Presumibilmente si sta utilizzando printf per emettere le colonne, in primo luogo. Puoi utilizzare extra modificatori nella stringa di formato per assicurarti che le cose vengano allineate.

  • Per stampare una colonna di una larghezza specifica (giustificato a destra), aggiungere la larghezza prima della bandiera formattazione, ad esempio, "% 10s" stamperà una colonna della larghezza di 10. Se la stringa è più lungo di 10 caratteri , la colonna sarà più lunga di quanto desideri, quindi scegli un valore massimo. Se la stringa è più corta, sarà riempita di spazi.
  • Per giustificare a sinistra una colonna, inserire un segno - davanti, ad es. "% -10s". Mi piace giustificare a sinistra le stringhe e giustificare i numeri, personalmente.
  • Se si stampano gli indirizzi, è possibile modificare i caratteri di riempimento da spazi a zero con uno zero iniziale: "% 010x".

per dare una più nell'esempio profondità:

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

Ciò stampare tre colonne come questo:

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

Ecco una soluzione awk: c_prog | awk '{ printf("%- 40s %- 40s\n", $1, $2); }'

2

ho scritto un piccolo programma che risolve questo problema usando Perl. Funziona anche per più colonne.

#!/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

Se si vuole fare l'elaborazione in Vim (al contrario di fissare il generatore), installare il superbaalign plugin ed eseguire il seguente:

ggVG 
\tsp 

Le prime rotture di comando verso il basso per gg (vai all'inizio del file), V (entra in modalità linea visiva), G (vai alla fine del file). Come combinazione, seleziona visivamente l'intero file. \tsp è una mappa di allineamento che si allinea sullo spazio bianco.

Se si preferisce fare le cose alla linea : di comando, è possibile utilizzare un separatore alternativo (ad esempio ###) e usare la linea di comando Allinea:

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

E 'più a lungo, ma si possono trovare più logica/memorabile.

33

Per una soluzione rapida-and-dirty, tubo attraverso colonna:

your_program | column -t 

Se è necessario includere spazi nei dati della colonna, quindi delimitano i campi con qualche personaggio come "|" e:

your_program | column -t -s "|" 

È possibile utilizzare qualsiasi carattere per un delimitatore e specificare con l'opzione -s. I caratteri di controllo sono possibili ma un po 'più complicati da usare.

Ma come Jay ha detto che è meglio fissare il programma per formattare l'output correttamente.

+0

È possibile utilizzare una funzionalità di Bash per specificare facilmente i caratteri di controllo, per esempio Tab: 'column -t -s $ '\ t'' –

+0

Attenzione: alla colonna non piacciono le linee" troppo lunghe ", e mentre la colonna" uomo "menziona una limitazione a 2048 byte, in pratica un paio di centinaia di byte è sufficiente per soffocare (almeno su Debian 8.3). –

2

Ho solo aggiungere manca in un altro opzioni risposte:

Emacs con Mx align-regexp, Mx align-string, ecc Per saperne di più a http://www.emacswiki.org/emacs/AlignCommands

shell POSIX (possibilmente costruire-in) comando printf:

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