如何从perl中的二进制数据集中选择行和计数值?

我希望你们中的任何人都可以帮助我。我有一个类似于这样的数据集: 0100010011 1011100100 0001001100 0101111011 0010000100 1101111011 0000111000 0001000101 1110000010 0001000011 0110111100 1001000001 此示例仅包含四个“段落”,每个段落有三行,每行10个数字。我的真实数据要大得多,它有1000个段落,每个段落100行,每行50个数字(所有二进制数据)。 我需要计算每段每列有“1”的次数。我一直在网上搜索,发现这段代码:
#!/usr/bin/perl
my @LineTotalsArray;

while (my $line = <stdin>) {
   print $line;
   chomp $line;

   my $index=0;
   for my $val ( split /t/, $line ) {
      $LineTotalsArray[ $index++ ] += $val;
   }
}

print join('=', @LineTotalsArray), "n";
这适用于“ALL”文件,它不区分段落,因此它给出了整个数据集中每列“T”的TOTAL帐户:4 5 4 7 5 5 5 5 5 6 0100010011 1011100100 0001001100 0101111011 0010000100 1101111011 0000111000 0001000101 1110000010 0001000011 0110111100 1001000001 4547555556 你有没有人知道在这种情况下我能做些什么?我怎么能告诉perl,我想每次做“这个”操作,比方说,“三行”? 感谢您的帮助,欢迎任何建议!     
已邀请:
如果输入数据集尚未处于块中:
#!/usr/bin/perl

use strict; use warnings;
use YAML;

my @counts;
my $every_n = 3;

while (my $row =  <DATA>) {
    last unless my @digits = $row =~ /([01])/g;
    $counts[($. - 1) / $every_n][$_] += $digits[$_] for 0 .. $#digits;
}

print Dump @counts;

__DATA__
0100010011
1011100100
0001001100
0101111011
0010000100
1101111011
0000111000
0001000101
1110000010
0001000011
0110111100
1001000001
如果输入数据集已经是块:
#!/usr/bin/perl

use strict; use warnings;
use YAML;

my @counts;

{
    local $/ = "";
    while ( my $chunk = <DATA> ) {
        while ( $chunk =~ /([01]+)/g ) {
            my @digits = $1 =~ /([01])/g;
            $counts[$. - 1][$_] += $digits[$_] for 0 .. $#digits;
        }
    }
}

print Dump @counts;

__DATA__
0100010011
1011100100
0001001100

0101111011
0010000100
1101111011

0000111000
0001000101
1110000010

0001000011
0110111100
1001000001
    
use strict;
use warnings;
use 5.010;
use Data::Dumper;

my %totals;

{
$/ = "nn";

while (my $chunk = <DATA>) {
   chomp $chunk;
   my @line_totals;

   for my $line (split /n/, $chunk) {
      my $index = 0;
      for (split //, $line ) {
          $line_totals[$index++] += $_;
      }
   }
   say $chunk;
   say @line_totals, "n";
   $totals{$chunk} = join '', @line_totals;
}
}

say Dumper %totals;
这仅在数据已经以块为单位分离时才有效,如您的示例所示。我们将输入记录分隔符设置为双换行符;在那之后,这是将块分成线条,将线条分成几部分的问题。 如果可以的话,我自己的一个问题:任何人都可以想到使用vec的解决方案吗? 编辑:我一直想知道我是否可以用正则表达式做内部部分。这是我的微弱尝试:
{
$/ = "nn";

while (<DATA>) {
   chomp;
   our @lines_total = ();
   my $index = 0;
   () = /(?
           (?<=^)
             ([0-1])(?{ $index = 0; $lines_total[$index] += $^N })
           |
             ([0-1])(?{ $lines_total[++$index] += $^N })
          )/xmg;
   say join '', @lines_total;

}
}
(不得不使用我们因为一个bug。它在perlre中解释)     
#!/usr/bin/perl
my @LineTotalsArray;

while (my $line = <stdin>) {
    print $line;
    chomp $line;

    my $index=0;

    chomp;
    my @val = (split /t/, $line);

    if (@val <= 1) {
            print "=", join('=', @LineTotalsArray), "n";
            @LineTotalsArray = undef;
    }

    else {
            for my $val ( split /t/, $line ) {
                    $LineTotalsArray[ $index++ ] += $val;
            }
    }
}

print "=", join('=', @LineTotalsArray), "n";
用空白行结束。您需要在每个空行上打印结果并清理阵列。有很多方法可以检查一个空白行(chomp后的0长度,正则表达式'^''等等......我可能会做零长度,但这只是对代码的快速更改)。     

要回复问题请先登录注册