2009-10-01 7 views
23

J'ai un programme C qui sort deux colonnes, complètement désalignées. La raison du désalignement est que les longueurs de mots dans la première colonne sont très différentes.Comment nettoyer les colonnes mal alignées dans du texte?

J'ai un fichier de sortie ouvert dans vi. Comment aligner rapidement ces deux colonnes? Je suis bien d'utiliser awk, perl, sed, et pas seulement le jeu d'outils vi (7.2). Aussi, pouvons-nous avoir une solution générique pour les fichiers avec plus de deux colonnes?

est un fichier exemple ici

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

Répondre

26

On peut supposer que vous utilisez printf pour sortir les colonnes en premier lieu. Vous pouvez utiliser des modificateurs supplémentaires dans votre chaîne de format pour vous assurer que les éléments sont alignés.

  • Pour imprimer une colonne d'une largeur spécifique (justifié à droite), ajouter la largeur du drapeau de la mise en forme, par exemple, « % 10s » imprimeront une colonne de largeur 10. Si votre chaîne est plus longue de 10 caractères , la colonne sera plus longue que vous voulez, alors choisissez une valeur maximale. Si la chaîne est plus courte, elle sera complétée avec des espaces.
  • Pour justifier une colonne à gauche, mettez un signe - devant, par exemple "% -10s". J'aime justifier les chaînes et justifier les nombres, personnellement.
  • Si vous imprimez des adresses, vous pouvez modifier les caractères de remplissage d'espaces en zéros avec un zéro non significatif: "% 010x".

Pour donner un plus dans l'exemple de la profondeur:

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

Ce imprimerait trois colonnes comme ceci:

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

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

2

j'ai écrit un petit programme qui résout ce problème en utilisant Perl. Cela fonctionne également pour plusieurs colonnes.

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

Si vous voulez faire le traitement dans vim (par opposition à la fixation du générateur), installez le superbealign plugin et exécutez la commande suivante:

ggVG 
\tsp 

La première commande interrompt jusqu'à gg (aller au début du fichier), V (entrer en mode ligne visuelle), G (aller à la fin du fichier). En combinaison, il sélectionne visuellement le fichier entier. \tsp est une carte d'alignement qui s'aligne sur l'espace blanc.

Si vous préférez faire les choses à la ligne de commande :, vous pouvez utiliser un séparateur alternatif (par exemple ###) et utiliser la ligne de commande Aligner:

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

Il est plus, mais vous pouvez trouver plus logique/mémorable.

33

Pour une solution rapide et sale, redirigez la colonne:

your_program | column -t 

Si vous devez inclure des espaces dans les données de colonne, puis délimitent les champs avec un certain caractère tel que « | » et:

your_program | column -t -s "|" 

Vous pouvez utiliser n'importe quel caractère pour un délimiteur et le spécifier avec le commutateur -s. Les caractères de contrôle sont possibles mais un peu plus difficile à travailler. Mais comme Jay l'a mentionné, vous feriez mieux de réparer votre programme pour formater correctement la sortie.

+0

Vous pouvez utiliser une fonctionnalité de Bash pour spécifier facilement des caractères de contrôle, par exemple Tab: 'column -t -s $ '\ t'' –

+0

Attention: la colonne n'aime pas les lignes qui sont" trop longues ", et alors que' man column' mentionne une limitation à 2048 octets, en pratique quelques centaines d'octets suffisent pour étouffer (sur Debian 8.3 au moins). –

2

ajouter manquant dans un autre des options de réponses:

Emacs avec Mx align-regexp, Mx align-string, etc. En savoir plus à http://www.emacswiki.org/emacs/AlignCommands shell POSIX

(peut-être construire en) commande printf:

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