我想逐行解析一个文件,每个文件包含两个整数,然后将这些值加在两个不同的变量中。我天真的做法是这样的:
my $i = 0;
my $j = 0;
foreach my $line (<INFILE>)
{
($i, $j) += ($line =~ /(\d+)\t(\d+)/);
}
但它会产生以下警告:
在void上下文中无用的私有变量
暗示使用+ =运算符触发标量中左侧的评估而不是列表上下文(如果我在这一点上错了,请纠正我。)
是否有可能在不使用数组或中间变量的情况下优雅地实现(可能在一行中)?
答案 0 :(得分:6)
不,这是因为表达式($i, $j) += (something, 1)
解析为仅将1
添加到$j
,而$i
挂在void上下文中。 Perl 5没有超级运算符或自动压缩赋值运算符,例如+=
。这有效:
my ($i, $j) = (0, 0);
foreach my $line (<INFILE>) {
my ($this_i, $this_j) = split /\t/, $line;
$i += $this_i;
$j += $this_j;
}
您可以通过使用复合数据结构而不是列的命名变量来避免重复。
答案 1 :(得分:3)
首先,你成对添加数组的方法不起作用(你自己发布的相关问题会给出一些提示)。
对于解析部分:如何分割线条?如果您的行格式相应(空格不应该是一个问题)。
split(/\t/, $line, 2)
如果你真的,真的想在一行中做,你可以做这样的事情(虽然我认为你不会称之为优雅):
my @a = (0, 0);
foreach my $line (<INFILE>)
{
@a = map { shift(@a)+$_ } split(/\t/, $line, 2);
}
对于@lines = ("11\t1\n", " 22 \t 2 \n", "33\t3");
的输入,它给了我@a = (6, 66)
我建议你使用我的答案的拆分部分,但不是添加部分。使用多条线路没有错!如果它使你的意图更清晰,那么更多的线条优于一条线条。但是现在我不再使用perl而是使用python,所以我的perl编码风格可能会产生“坏”的影响......
答案 2 :(得分:2)
很有可能在每次添加时交换该对,这意味着您总是在每对中添加相同的元素。 (如果需要,这可以推广用于旋转多元素阵列。)
use strict;
use warnings;
my @pair = (0, 0);
while (<DATA>) {
@pair = ($pair[1], $pair[0] + $_) for /\d+/g;
}
print "@pair\n";
__DATA__
99 42
12 15
18 14
<强>输出强>
129 71
答案 3 :(得分:0)
这是另一种选择:
use Modern::Perl;
my $i = my $j = 0;
map{$i += $_->[0]; $j += $_->[1]} [split] for <DATA>;
say "$i - $j";
__DATA__
1 2
3 4
5 6
7 8
输出:
16 - 20