它应该是一个简单的嵌套foreach循环,但它不起作用,真的开始惹恼我,我无法弄清楚这一点!仍然是一个perl初学者,但我认为我现在明白这一点。有人可以向我解释我哪里出错了吗?这个想法很简单:2个文件,1个小,1个大,我想要的小信息。两者都有独特的id。比较并匹配id并输出一个新的小文件,并在小文件中添加信息。
我有两段代码:1代码没有严格,1代表,两者都不起作用。我知道要使用严格但我仍然很好奇为什么没有严格的人也没有工作。
WITOUT STRICTS:
if ($#ARGV != 2){
print "input_file1 input_file2 output_file\n";
exit;
}
$inputfile1=$ARGV[0];
$inputfile2=$ARGV[1];
$outputfile1=$ARGV[2];
open(INFILE1,$inputfile1) || die "No inputfile :$!\n";
open(INFILE2,$inputfile2) || die "No inputfile :$!\n";
open(OUTFILE_1,">$outputfile1") || die "No outputfile :$!\n";
$i = 0;
$j = 0;
@infile1=<INFILE1>;
@infile2=<INFILE2>;
foreach ( @infile1 ){
@elements = split(";",$infile1[$i]);
$id1 = $elements[3];
print "1. $id1\n";
$lat = $elements[5];
$lon = $elements[6];
$lat =~ s/,/./;
$lon =~ s/,/./;
print "2. $lat\n";
print "3. $lon\n";
foreach ( @infile2 ){
@loopelements = split(";",$infile2[$j]);
$id2 = $loopelements[4];
print "4. $id2\n";
if ($id1 == $id2){
print OUTFILE_1 "$loopelements[0];$loopelements[1];$loopelements[2];$loopelements[3];$loopelements[4];$lat,$lon\n";
};
$j = $j+1;
};
@elements = join(";",@elements); # add ';' to all elements
#print "$i\r";
$i = $i+1;
}
close(INFILE1);
close(INFILE2);
close(OUTFILE_1);
如果我没有弄错的话,没有错误就是第二个循环不会启动。
WITH STRICTS:
use strict;
use warnings;
my $inputfile1 = shift || die "Give input!\n";
my $inputfile2 = shift || die "Give more input!\n";
my $outputfile = shift || die "Give output!\n";
open my $INFILE1, '<', $inputfile1 or die "In use/Not found :$!\n";
open my $INFILE2, '<', $inputfile2 or die "In use/Not found :$!\n";
open my $OUTFILE, '>', $outputfile or die "In use/Not found :$!\n";
my $i = 0;
my $j = 0;
foreach ( my $infile1 = <$INFILE1> ){
my @elements = split(";",$infile1[$i]);
my $id1 = $elements[3];
print "1: $id1\n";
my $lat = $elements[5];
my $lon = $elements[6];
$lat =~ s/,/./;
$lon =~ s/,/./;
print "2: $lat\n";
print "3: $lon\n";
foreach ( my $infile2 = <$INFILE2> ){
my @loopelements = split(";",$infile2[$j]);
my $id2 = $loopelements[4];
print "4: $id2\n";
if ($id1 == $id2){
print $OUTFILE "$loopelements[0];$loopelements[1];$loopelements[2];$loopelements[3];$loopelements[4];$lat,$lon\n";
};
$j = $j+1;
};
#@elements = join(";",@elements); # add ';' to all elements
#print "$i\r";
$i = $i+1;
}
close($INFILE1);
close($INFILE2);
close($OUTFILE);
严格的错误:
Global symbol "@infile1" requires explicit package name at Z:\Data-Content\Data\test\jan\bestemming_zonder_acco\add_latlon_dest_test.pl line 16.
Global symbol "@infile2" requires explicit package name at Z:\Data-Content\Data\test\jan\bestemming_zonder_acco\add_latlon_dest_test.pl line 31.
答案 0 :(得分:2)
由于对sigils($和@字符)的混淆指示变量是标量还是数组,您的'严格'实现会给您带来错误。在循环语句中,您正在将文件的每一行读入名为$ infile1的标量中,但在以下行中,您尝试访问数组@ infile1的元素。这些与变量无关,而perl告诉你后者未被声明。
“严格”实现的另一个问题是您正在读取循环内的文件。这意味着对于嵌套循环,您将在外部循环的第一次迭代中读取文件2,对于所有后续迭代,内部循环将无法读取任何行。
我错过了foreven / while问题,stevenl指出,即使修复了限制问题,也会让你只用一次迭代进行foreach循环。
我不确定你的unstrict脚本有什么问题。
但我根本不会使用嵌套循环来处理两个文件。我会解开循环,所以大致看起来像这样:
my %cord;
while ( my $line = <$INFILE1> ) {
my @elements = split /;/, $line;
$cord{ $elements[3] } = "$elements[5],$elements[6]";
}
while ( my $line = <$INFILE2> ) {
my @elements = split /;/, $line;
if ( exists %coord{ $elements[4] } ) {
print $OUTFILE "....;$cord{ $elements4 }\n";
}
}
答案 1 :(得分:1)
我无法确切地看到非严格版本的问题在哪里。你遇到的问题是什么?
严格版本的问题尤其在以下两行中:
foreach ( my $infile1 = <$INFILE1> ){
my @elements = split(";",$infile1[$i]);
第一行中有一个标量$infile1
,但您在下一行中将其视为一个数组。另外,将foreach
更改为while
(见下文)。
一些评论。
对于非严格版本,您可以将循环折叠为C样式的for
循环:
for (my $i = 0; $i < @infile1; $i++) {
...
}
如果你完全不使用数组索引,那么可以更简单地阅读:
foreach my $infile1 (@infile1) {
my @elements = split ';', $infile1;
...
}
但是对于较大的文件,可能需要一段时间才能将整个文件粘贴到数组中。所以在你去的时候迭代文件可能会更好:
while (my $infile = <$INFILE1>) {
...
}
请注意,最后一点应该是严格版本的外观。你需要while
循环而不是foreach
循环,因为将<$INFILE1>
赋给标量意味着它将仅返回下一行,只要有另一行,就会返回true文件。 (因此,foreach
只会让第一行循环。)
答案 2 :(得分:0)
在内部foreach循环运行之前,您不会重置$ j。因此,第二次运行内部循环时,您将尝试访问超出数组末尾的元素。这个错误存在于严格和非严格版本中。
你根本不应该使用$ i和$ j; foreach的意思是它会自动为你获取每个元素。以下是在内循环中正确使用foreach的示例:
foreach my $line ( @infile2 ){
@loopelements = split(";",$line);
#...now do stuff as before
}
这会将@infile的每个元素连续放入变量$ line中,直到您完成所有数组。