-1
Test.txt
tom 
cat=0  bat=1  mat=0  pen=1
ironman122_bore.1 
cat=8e-7  bat=8.001e-7  mat=5e-6  pen=200.001e-6     
batmanbegin_nice.1  
cat=10  bat=1  mat=0.25  pen=49.25   

这是我的输入示例,我希望我的输出类似于 Out.txt

Out.txt
name                cat       bat       mat       pen               
tom                 -         1         -         -    
ironman122_bore.1   8e-7      8.001e-7  5e-6      200.001e-6
batmanbegin_nice.1  10        1         0.25      49.25 

这是我尝试过的

my $pr = "%-12s"; 
my @headers = qw/name cat bat mat pen/; 
my %names; 
while (<DATA>) {     
    chomp;     
    my $line = <DATA>;     
    %{$names{$_}} = split /=|\s+/, $line; 
}  
printf $pr x @headers . "\n", @headers; 
for (keys %names) {     
    my @ds = ($_);     
    for my $k (@headers[1..$#headers]) {
       my $v = $names{$_}->{$k};         
       push @ds, $v ? $v : '-';     
    }     
    printf $pr x @ds . "\n", @ds; 
}

但我得到一个输出

name          cat       bat       mat       pen               
tom        -         1         -         -    
ironman122_bore.1  8e-7      8.001e-7  5e-6      200.001e-6
batmanbegin_nice.1  10         1         0.25     49.25 

如何修改代码以获得 Out.txt 中所示的对齐输出?当我使用与我作为输入给出的数据相似的实际数据时,我无法达到我的预期。

编辑:示例输入已与预期结果一起更改

4

3 回答 3

0

为对齐输出填充任何字符串的一种简单方法是使用 sprintf。例如:您希望 2 列均匀地大小为 20 个字符,并带有分隔符。您还希望您的右列在您指定的文本之后左对齐和填充。没问题:

print sprintf("# %20s | %-20s #","Column1","Column2")."\n";

将打印:

username@hostname:~$ perl -e 'print sprintf("# %20s | %-20s #","Column1","Column2")."\n";'
#              Column1 | Column2              #
于 2012-08-15T08:07:49.900 回答
0

使用早期数据

发布的代码对我来说很好。

输出

name        a           b           c           d           e           
bobby       60          74.2        8           -           10.25       
tom         10.1        2           300.89      4145        55

您正在查看的字体是固定宽度吗?


使用新数据

未对齐的原因是“名称”列下的某些项目超过 12 个字符(例如,“batmanbegin_nice.1”的长度为 18 个字符)。

(s)printf不会按照原始帖子中指定的方式将字符串截断为 12 个字符。

要截断,请在和.之间指定一个:%12

printf '%.12s', 'batmanbegin_nice.1' ;  # "batmanbegin_"

如果不需要截断,请将字符串长度增加到%20s.

至于最大长度的动态检测,这需要另一个问题:)

于 2012-08-15T07:52:16.727 回答
0
#!/usr/bin/env perl

use strict;
use warnings;
use List::MoreUtils qw(uniq);

my $pr = "%-24s";
my @headers = qw/name/;
my %names;
while (<DATA>) {
    chomp;
    s/^\s+//g;
    s/\s+$//g;
    my $line = <DATA>;
    $line =~ s/^\s+//g;
    $line =~ s/\s+$//g;
    %{$names{$_}} = split /\s*=\s*|\s+/, $line;
}
push @headers, uniq sort map { keys %{$names{$_}}; } keys %names;
printf $pr x @headers . "\n", @headers;
for (keys %names) {
    my @ds = ($_);
    for my $k (@headers[1..$#headers]) {
        my $v = $names{$_}->{$k};
        push @ds, defined $v ? $v : '-';
    }
    printf $pr x @ds . "\n", @ds;
}

__DATA__
 tom
cat = 0  bat =1  mat= 0  pen=1
ironman122_core.1
 cat= 8e-7  bat= 8.001e-7  mat= 5e-6  pen= 200.001e-6
batmanbegin_core.1
cat=10  bat = 1  mat= 0.25  pen= 49.25

输出:

name                    bat                     cat                     mat                     pen                     
tom                     1                       0                       0                       1                       
batmanbegin_core.1      1                       10                      0.25                    49.25                   
ironman122_core.1       8.001e-7                8e-7                    5e-6                    200.001e-6  
于 2012-08-15T08:04:08.573 回答