我是perl的初学者,所以请耐心等待。
我有2个文件:
1
2
3
和
2
4
5
6
我想创建一个新文件,它是上述两个文件的总和:
输出文件:
3
6
8
6
我现在正在做的是将文件作为数组读取并逐个元素地添加它们。
要添加数组,我使用以下内容:
$asum[@asum] = $array1[@asum] + $array2[@asum] while defined $array1[@asum] or defined $array2[@asum];
但这会产生以下错误:
Argument "M-oM-;M-?3" isn't numeric in addition (+) at perl_ii.pl line 30.
Argument "M-oM-;M-?1" isn't numeric in addition (+) at perl_ii.pl line 30.
Use of uninitialized value in addition (+) at perl_ii.pl line 30.
我使用以下代码将文件读取为数组:
use strict;
use warnings;
my @array1;
open(my $fh, "<", "file1.txt") or die "Failed to open file1\n";
while(<$fh>) {
chomp;
push @array1, $_;
}
close $fh;
my @array2;
open(my $fh1, "<", "file2.txt") or die "Failed to open file2\n";
while(<$fh1>) {
chomp;
push @array2, $_;
}
close $fh1 ;
任何人都可以告诉我如何解决这个问题,或者完全采取更好的方法?
答案 0 :(得分:3)
这是另一个使用菱形<>
文件读取运算符的Perl解决方案。这将读入命令行中指定的文件(而不是在程序中显式打开它们)。抱歉,我无法找到解释此内容的文档部分。
此程序的命令行如下所示:
perl myprogram.pl file1 file2 > outputfile
其中file1和file2是2个输入文件,outputfile是要打印添加结果的文件。
#!/usr/bin/perl
use strict;
use warnings;
my @sums;
my $i = 0;
while (my $num = <>) {
$sums[$i++] += $num;
$i = 0 if eof;
}
print "$_\n" for @sums;
注意:$i
在文件末尾重置为零(在这种情况下,在读取第一个文件之后)。实际上,在读取第二个文件后它也会重置为0。但是,这对程序没有影响,因为在示例中的第二个文件之后没有要读取的文件。
答案 1 :(得分:3)
以下解决方案使程序的内存占用量与文件大小无关。相反,现在内存占用量仅取决于文件的 number :
FixedLengthTokenizer
答案 2 :(得分:2)
您的脚本现在有两个不同的问题:
第一个错误
发生论证&#34; M-oM-; M-?3&#34;在perl_ii.pl行另外(+)不是数字 30
是因为您的输入文件以Unicode格式保存,第一行使用&#34; \ xFF \ xFE&#34; BOM字节。 要简单地修复它,只需将文件重新保存为ANSI文本。如果需要Unicode,则从您从文件中读取的第一个字符串中删除这些字节。
第二个错误
发生在perl_ii.pl第30行另外使用未初始化的值(+)。
是因为您访问了第一个不存在的数组中的第4个元素。请记住,您选择最大输入数组长度作为索引限制。要修复它,只需为input元素添加以下条件:
$asum[@asum] = (@asum < @array1 ? $array1[@asum] : 0) + (@asum < @array2 ? $array2[@asum] : 0) while defined $array1[@asum] or defined $array2[@asum];
答案 3 :(得分:2)
读取两个文件的逻辑是一样的,我建议使用一个子程序并调用它两次:
#!/usr/bin/env perl
use strict;
use warnings;
my @array1 = read_into_array('file1.txt');
my @array2 = read_into_array('file2.txt');
sub read_into_array
{
my $filename = shift;
my @array;
open(my $fh, "<", $filename) or die "Failed to open $filename: $!\n";
while(<$fh>) {
chomp;
push @array, $_;
}
close $fh;
return @array;
}
但这只是我做出的一个观察,而不是你问题的解决方案。作为CodeFuller already said,您应该将文件重新保存为纯ASCII而不是UTF-8。
第二个问题,使用未初始化的值(+),也可以使用Perl 5.10中引入的Logical Defined Or运算符//
来解决:
my @asum;
$asum[@asum] = ($array1[@asum] // 0)
+ ($array2[@asum] // 0)
while defined $array1[@asum] or defined $array2[@asum];
不,这不是评论,而是与||
非常相似的运营商。不同之处在于,当左侧(lhs)为undef
时触发,而当{lhs 虚假时触发||
(即0
, ''
或undef
)。因此
$array1[@asum] // 0
如果0
为undef,则给出$array1[@asum]
。它与
defined($array1[@asum]) ? $array1[@asum] : 0
答案 4 :(得分:1)
完全不同的方法:
$ paste -d '+' file1 file2 | sed 's/^+//;s/+$//' | bc
3
6
8
6
paste
命令打印彼此相邻的文件,以+
符号分隔:
$ paste -d '+' file1 file2
1+2
2+4
3+5
+6
sed命令会删除前导和尾随+
符号,因为这些符号会bc
:
$ paste -d '+' file1 file2 | sed 's/^+//;s/+$//'
1+2
2+4
3+5
6
bc
最终计算总和。
答案 5 :(得分:1)
以英语形式更新Sinan’s approach:
#!/usr/bin/env perl
use 5.010; use strict; use warnings;
use autodie;
use List::Util 'sum';
my @fh = map { open my $fh, '<', $_; $fh } @ARGV;
while ( my @value = grep { defined } map { scalar readline $_ } @fh ) {
say sum @value;
@fh = grep { not eof $_ } @fh if @value < @fh;
}