Ils n'ont manifestement pas un espacement égal entre chaque élément de la ligne, mais ils sont alignés sur la base des colonnes. Je baguette pour éditer le 3e élément de R3 de XA à XAHBB mais impossible de maintenir l'alignement des colonnes
R1 X XA 0i 1i H 0i R2 X XA 1i 1i H 0i R3 X XAHBB 1i 1i H 0i R4 X XA 1i 1i H 0i R5 X XA 1i 1i H 0i R6 X XA 0i 0i X 0i
Ma sortie actuelle est comme indiqué ci-dessous
R1 X XA 0i 1i H 0i R2 X XA 1i 1i H 0i R3 X XAHBB 1i 1i H 0i R4 X XA 1i 1i H 0i R5 X XA 1i 1i H 0i R6 X XA 0i 0i X 0i
Où, comme mon résultat attendu devrait ressemblez à ceci ci-dessous
my $cur_line_num = 1; while(<Sourcefile>){ my @RowEdit = split (" ",$_); if($RowEdit[0]=~ m/^R3$/s){ $RowEdit[2]="RowEdit[2]HBB" } my $curr_line = join(" ", @RowEdit) print $newfile "curr_line\n"; $cur_line_num++; } print "$cur_line_num\n";
Comment maintenir l'alignement des colonnes lors de l'édition d'un fichier?
3 Réponses :
C'est à cela que sert Text :: Table :
#!/usr/bin/perl use warnings; use strict; use Text::Table; my $table = 'Text::Table'->new; while (<DATA>) { my @RowEdit = split ' '; if ($RowEdit[0] eq 'R3') { $RowEdit[2] .= 'HBB'; } $table->add(@RowEdit); } print $table; print $. + 1, "\n"; __DATA__ R1 X XA 0i 1i H 0i R2 X XA 1i 1i H 0i R3 X XA 1i 1i H 0i R4 X XA 1i 1i H 0i R5 X XA 1i 1i H 0i R6 X XA 0i 0i X 0i
Notez également tous les autres petits changements que j'ai faits:
$.
. / s
change le comportement de .
dans une regex. Cela n'a aucun sens de l'utiliser dans une regex qui ne contient pas de point. De plus, eq
peut être utilisé pour l'équialité des chaînes s'il n'y a qu'une seule chaîne qui correspond à l'expression régulière - elle est plus facile à lire et plus rapide à exécuter. $ _
comme deuxième argument si aucun n'est fourni. Taper $ _
n'importe où en dehors de grep
ou de map
est une odeur de code - soit c'est quelque chose qui vaut un nom, ou peut être écrit sans. li>
. =
. y a-t-il un moyen de le faire sans utiliser l'extension Text :: Table? avec des commandes perl basiques
Vous pouvez toujours lire le code source de Text :: Table - il suffit de cliquer sur Source .
sprintf
et format
vous donnent quelque chose de similaire, mais ils ne sont pas de nature dynamique. Vous devrez choisir vos largeurs de colonne à l'avance (bien que vous puissiez peut-être `` détecter '' quelle serait la cellule la plus large d'une colonne et l'utiliser)
J'imprime ces données d'un fichier vers une autre solution de sprintf
fonctionnera avec ce scénario @Sobrique
Vous pouvez le faire avec printf ()
. Mais vous devez faire deux passes sur les données (car il n'y a aucun moyen de savoir quelle est la largeur de colonne la plus large avant d'avoir vu chaque enregistrement de données).
Quelque chose comme ça semble faire l'affaire.
R1 X XA 0i 1i H 0i R2 X XA 1i 1i H 0i R3 X XAHBB 1i 1i H 0i R4 X XA 1i 1i H 0i R5 X XA 1i 1i H 0i R6 X XA 0i 0i X 0i
Le résultat est:
#!/usr/bin/perl use strict; use warnings; my @widths; # Store the max widths for each column my @data; # Store the actual data while (<DATA>) { my @row; # Use the first line to initialise the @widths array if ($. == 1) { @row = /(\S+\s*)/g; @widths = map { length() - 1} @row; # Subtract 1 for gutter @row = map { s/\s+$//; $_ } @row; # Remove trailing whitespace } else { @row = split; } # Split the data my @row = split; # Store the split data push @data, \@row; # Make the (optional) transformation $row[2] .= 'HBB' if $row[0] eq 'R3'; # Look at each column in this row of data and # compare it to the widest data that we've previously # seen in that column. for my $i (0 .. $#row) { $widths[$i] = length $row[$i] if length $row[$i] > ($widths[$i] // 0); } } # Create a printf output format using the column # widths we've stored in @widths my $fmt = join ' ', map { "%-${_}s" } @widths; # Use printf to display each line of data. printf "$fmt\n", @$_ for @data; __DATA__ R1 X XA 0i 1i H 0i R2 X XA 1i 1i H 0i R3 X XA 1i 1i H 0i R4 X XA 1i 1i H 0i R5 X XA 1i 1i H 0i R6 X XA 0i 0i X 0i
Mais je pense que la solution Text :: Table est meilleure :-)
Comme il s'agit de l'une des tâches pour lesquelles Perl a été initialement écrit ( Practical Extraction and Reporting Language a >), alors pour être complet, il faut également mentionner les bons vieux formats Perl simples, voir man perlform
. Par exemple, format STDOUT =
@<<<<< @ @<<<<, ....
$col1, $col2, $col3, ...
.
for my ... (...) {
# set $col1 .... and then
write
}