如何从数据中选择最后一列并打印它的总和?
How to pick last column from data and print sum of it?
正在尝试:
my @header = split(/\,/,$recIn,-1);
print "Header Feed Date: $header[2]\n";
chop($header[2]);
use warnings;
use strict;
use feature 'say';
my $tot = 0;
my $header = <>;
while (<>) {
$tot += (split /,/)[-1];
}
say join ',', 'FINAL', $.-1, $tot;
<>
operator reads lines of files submitted at command-line at invocation. The $.
variable 是 last-used 文件句柄的当前行号。
数字(及其小数位数)的格式与 printf
相得益彰。
以上处理文件中的数据。但是,问题中显示的最后一行 FINAL...
确实是输入文件的最后一行,需要检查。那也不应该被处理所以我们需要添加一个检查
while (<>) {
if (/^\s*FINAL/) {
my @fields = split /,/;
if ($.-1 != $fields[1] or $tot != $fields[-1]) {
warn "Wrong FINAL line: $_";
}
last;
}
$tot += (split /,/)[-1];
}
但随后我们多次(三)次处理该行。它更好,当然也更适合检查输入数据,首先 split
将每一行放入一个数组并使用就绪数组
while (<>) {
my @fields = split /,/;
# Is this the last line, with a summary to be checked?
if ($fields[0] eq 'FINAL') {
if ($.-1 != $fields[1] or $tot != $fields[-1]) {
warn "Wrong FINAL line: $_";
}
last;
}
# Validate input if/as needed
$tot += $fields[-1];
}
仅当文件相当大或处理许多此类文件时,这种添加的数组结构才会明显(并且负面地)反映效率。但是,如果输入数据确实需要以任何方式检查格式、有效性或 pre-processed,那么当然别无选择。 (在非常短的文件中,这可能更有效,但很难检测到这一点,因为它只有一行。)
另一种选择,如果文件不是太大,首先将所有行读入一个数组,剥离不需要的第一行(header)和最后一个摘要行,然后处理其余部分
my @lines = <>;
chomp @lines;
my $header = shift @lines;
my $final = pop @lines;
foreach my $line (@lines) {
# or split into an array for checking of various fields etc
$tot += (split /,/, $line)[-1];
}
say join ',', 'FINAL', scalar @lines, $tot;
CHECK_FINAL_LINE: {
my @fields = split /,/, $final;
if ( $fields[1] != @lines or $fields[-1] != $tot ) {
warn "FINAL summary line wrong: $final";
}
};
现在我们避免检查每一行是否是最后一行。
数据行数是数组@lines
的长度,当@lines
数组用在标量context时产生,就像在if
中最后一块。我将检查放在一个块中,以避免为程序的其余部分引入 @fields
数组(这样它的范围仅限于该块),我将块命名为 CHECK_FINAL_LINE
for convenience/clarity.该块不是必需的。
虽然我们有一个列表上下文,但在打印最终计算结果的行中,由 print
(以及 say
)强加,我们实际上需要一个显式的 scalar
.
正在尝试:
my @header = split(/\,/,$recIn,-1);
print "Header Feed Date: $header[2]\n";
chop($header[2]);
use warnings;
use strict;
use feature 'say';
my $tot = 0;
my $header = <>;
while (<>) {
$tot += (split /,/)[-1];
}
say join ',', 'FINAL', $.-1, $tot;
<>
operator reads lines of files submitted at command-line at invocation. The $.
variable 是 last-used 文件句柄的当前行号。
数字(及其小数位数)的格式与 printf
相得益彰。
以上处理文件中的数据。但是,问题中显示的最后一行 FINAL...
确实是输入文件的最后一行,需要检查。那也不应该被处理所以我们需要添加一个检查
while (<>) {
if (/^\s*FINAL/) {
my @fields = split /,/;
if ($.-1 != $fields[1] or $tot != $fields[-1]) {
warn "Wrong FINAL line: $_";
}
last;
}
$tot += (split /,/)[-1];
}
但随后我们多次(三)次处理该行。它更好,当然也更适合检查输入数据,首先 split
将每一行放入一个数组并使用就绪数组
while (<>) {
my @fields = split /,/;
# Is this the last line, with a summary to be checked?
if ($fields[0] eq 'FINAL') {
if ($.-1 != $fields[1] or $tot != $fields[-1]) {
warn "Wrong FINAL line: $_";
}
last;
}
# Validate input if/as needed
$tot += $fields[-1];
}
仅当文件相当大或处理许多此类文件时,这种添加的数组结构才会明显(并且负面地)反映效率。但是,如果输入数据确实需要以任何方式检查格式、有效性或 pre-processed,那么当然别无选择。 (在非常短的文件中,这可能更有效,但很难检测到这一点,因为它只有一行。)
另一种选择,如果文件不是太大,首先将所有行读入一个数组,剥离不需要的第一行(header)和最后一个摘要行,然后处理其余部分
my @lines = <>;
chomp @lines;
my $header = shift @lines;
my $final = pop @lines;
foreach my $line (@lines) {
# or split into an array for checking of various fields etc
$tot += (split /,/, $line)[-1];
}
say join ',', 'FINAL', scalar @lines, $tot;
CHECK_FINAL_LINE: {
my @fields = split /,/, $final;
if ( $fields[1] != @lines or $fields[-1] != $tot ) {
warn "FINAL summary line wrong: $final";
}
};
现在我们避免检查每一行是否是最后一行。
数据行数是数组@lines
的长度,当@lines
数组用在标量context时产生,就像在if
中最后一块。我将检查放在一个块中,以避免为程序的其余部分引入 @fields
数组(这样它的范围仅限于该块),我将块命名为 CHECK_FINAL_LINE
for convenience/clarity.该块不是必需的。
虽然我们有一个列表上下文,但在打印最终计算结果的行中,由 print
(以及 say
)强加,我们实际上需要一个显式的 scalar
.