【问题标题】:How to print data in column form in Perl?如何在 Perl 中以列的形式打印数据?
【发布时间】:2015-10-01 19:44:58
【问题描述】:

我有一个程序可以按行打印数组的内容。我希望它在相邻的列中打印每个数组。

这是代码:

#!/usr/local/bin/perl

use strict;
use warnings;

my @M_array;
my @F_array;

open (my $input, "<", 'ssbn1898.txt');

while ( <$input> ) {

    chomp;

    my ( $name, $id ) = split ( /,/ ); 

    if ( $id eq "M" ) {
        push ( @M_array, $name );
    }
    else {
        push ( @F_array, $name ); 
    }
}
close ( $input );

print "M: @M_array \n"; 
print "F: @F_array \n";

这是可能的还是我正在尝试做一些无法做到的事情?

所需格式:

M      F 
Namem1 Namef1 
Namem2 Namef2 

【问题讨论】:

  • 添加您想要的格式作为输出将有助于提供更好的答案。
  • 我想要类似的东西
  • MF Namem1 Namef1 Namem2 Namef2

标签: perl output-formatting


【解决方案1】:

您可以使用join 函数在数据之间添加任何您想要的分隔符,下面的示例格式化由制表符分隔的数组中的数据:

...
use List::MoreUtils qw/pairwise/;

my $separator = "\t";
print join($separator, qw(M F)), "\n";
print join(
   "\n", 
   pairwise { ( $a // '') . $separator . ( $b // '') } @M_array, @F_array
), "\n";
...

【讨论】:

  • 可能值得一提的是,// 是 perl 5.10 以后的版本。 5.8.8 已经很老了,但似乎还在!
【解决方案2】:

我认为,您应该使用 Perl 格式。看看Perl documentation。您可能希望在您的情况下使用 @* 格式字段。

我扩展了您的代码以便在最后打印所需的输出

use strict;
use warnings;

my @M_array;
my @F_array;

open (my $input, "<", 'ssbn1898.txt');

while ( <$input> ) {

    chomp;

    my ( $name, $id ) = split ( /,/ ); 

    if ( $id eq "M" ) {
        push ( @M_array, $name );
    }
    else {
        push ( @F_array, $name ); 
    }
}
close ( $input );

unshift @M_array, 'M';
unshift @F_array, 'F';

my $namem; 
my $namef;

my $max = 0;

$max = (length($_) gt $max  ? length($_) : $max) for @M_array;
my $w = '@' . '<' x $max;

eval "
format STDOUT = 
$w @*
\$namem, \$namef 
.
";

while ( @M_array or @F_array) {

    $namem = shift @M_array || '';
    $namef = shift @F_array || '';

    write;

}

【讨论】:

  • 我认为这可以通过一个例子得到很大改善。
  • @Sobrique Perl 的format 看起来很复杂(对于 C/C++ 程序员)。你用过成功吗?
  • 大约 15 年前,是的。从此没有。 (这也是我热衷于示例的部分原因:))
  • @Sobrique:嗯,我通常不会在命令行上创建具有对齐列的输出。我更愿意创建一些结构化的输出并让另一个程序进行格式化。嗯......这可能是一个更好的答案;-)
  • @Wolf 是的,我也发现了问题并相应地增强了代码。我删除了打印语句。
【解决方案3】:

join 可能是采用tabs 的最简单方法,可以很好地对齐您的列。

join ( "\t", @array ),

另外,perl 允许通过(s)printf 格式化:

printf ( "%-10s %-10s", "first", "second" );

或者更详细的'format'

鉴于您尝试做的是将两个数组放入列中:

#!/usr/local/bin/perl
use strict;
use warnings;

my $format = "%-10s\t%-10s\n";

my @M_array = qw ( M1 M2 M3 M4 M5 );
my @F_array = qw ( F1 F2 F3 );
my $maxrows = $#M_array > $#F_array ?  $#M_array : $#F_array; 

printf ( $format, "M", "F" );
for my $rownum ( 0..$maxrows ) { 
    printf ( $format, $M_array[$rownum] // '', $F_array[$rownum] // '' );

}

这将打印标题行,然后循环遍历数组,一次打印一行。 // 是一个条件操作,用于测试是否定义了某些内容。它仅在较新的 perls 中可用*。在旧版本中,|| 可以解决问题 - 它几乎相同,但处理 ''0 略有不同。

* Perl 5.10 开始,所以相当安全,但值得一提的是,因为一些系统仍在运行 perl 5.8。

【讨论】:

  • printf 当然比print sprintf 组合更容易使用。我遇到语法“错误”,更正后,再次出现错误:“使用未初始化的值......”也许我的 Perl 太旧(5.8.8)?
  • 是的。 // 是 perl 5.10 的一个特性。 || 将在 5.8.8 中工作。是的,5.8.8 真的很老了——作为 2008 年的版本,它正式结束了生命周期。 (但你不是唯一一个以任何方式使用它的人)
  • 好的,我现在用 perl 5.8.8 运行它。这个答案的问题是,SO 语法荧光笔不理解它。所以它读起来绝对令人困惑。也许最好也添加||
【解决方案4】:

您可以使用sprintf 函数格式化输出,但还有一些问题需要解决:如果数组的条目数不同怎么办?为此,您需要一个占位符。一列必须包含多少个字母?应该如何对齐?一些说明代码:

#!/usr/bin/perl
use strict;
use warnings;

my @m = (1, 2, 3);
my @f = (11, 22, 33, 44);

# calculate how many rows to display
my $max = @m;
if (@m < @f) {
    $max = @f;
}

# placeholder for missing data
my $none = '-';

# formatting 20 chars per column, left aligned
my $fmt = "%-20s%-20s\n";

# print header
print sprintf($fmt, "M", "F");

# print data rows
foreach my $i (0..$max-1) {
    print sprintf($fmt, ($m[$i] or $none), ($f[$i] or $none));
}

如果您对更复杂的格式(例如居中对齐的文本)感兴趣,您应该切换到special formatting capabilities Perl 提供的报告生成。

【讨论】:

    【解决方案5】:

    借鉴@HunterMcMillen

    use strict;
    use warnings;
    use feature "say";
    
    local $, = "\t";   # separator when printing list
    
    my $i = (@F_array > @M_array) ? $#F_array : $#M_array;
    
    say qw(M F);
    say $M_array[$i] //"", $F_array[$i] //"" for 0 .. $i;
    

    【讨论】:

      【解决方案6】:

      我猜 Text::Table 是 perl 发行版附带的必需模块(只需要安装)。请阅读以下文档 -

      Documentation of Text::Table

      您需要将内容作为数组传递给 add() 方法,它会为您创造奇迹。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-13
        • 1970-01-01
        • 1970-01-01
        • 2023-02-17
        • 1970-01-01
        • 2020-07-18
        • 2017-03-19
        • 1970-01-01
        相关资源
        最近更新 更多