好的,我有2个文件。一个文件是每10分钟更新一次的数据,而第二个文件是先前使用的数据。我要做的是从新文件中取一行并循环遍历第二个文件的每一行,看看它是否匹配一个。如果它确实我不想使用它,但如果没有匹配,我想将它添加到字符串。在我到目前为止所做的事情中,似乎即使有一个检查也没有找到匹配。这是我所拥有的以及我从两个文件中使用的数据样本。 CHECKHAIL和USEDHAIL是两个文件
while(my $toBeChecked = <CHECKHAIL>){
my $found = 0;
seek USEDHAIL, 0, 0 or die "$0: seek: $!";
while(my $hailCheck = <USEDHAIL>){
if( $toBeChecked == $hailCheck){
$found += 1;
}
}
print USEDHAIL $toBeChecked;
if ($found == 0){
$toEmail .= $toBeChecked;
}
}
print $toEmail;
return;
}
CHECKHAIL样本数据
2226 175 2 NE LAWRENCE DEADWOOD SD 44.4 -103.7 (UNR)
2305 200 2 S SISKIYOU GREENVIEW CA 41.52 -122.9 2 INCH HAIL REPORTED WITH STORM JUST SOUTH OF GREENVIEW. (MFR)
2350 200 DANIELS E FLAXVILLE MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW)
2350 175 5 N DANIELS RICHLAND MT 48.89 -106.05 DESTROYED CROPS (GGW)
USEDHAIL样本数据
2226 175 2 NE LAWRENCE DEADWOOD SD 44.4 -103.7 (UNR)
2305 200 2 S SISKIYOU GREENVIEW CA 41.52 -122.9 2 INCH HAIL REPORTED WITH STORM JUST SOUTH OF GREENVIEW. (MFR)
答案 0 :(得分:3)
由于
,它永远不会有成功的机会while(<USEDHAIL>){
my $hailCheck = $_;
if( $toBeChecked eq $hailCheck){
$found += 1;
}else{
return; ### XXX
}
}
在第一个不匹配时,sub返回其调用者。您的意思可能是next
,但为了简洁起见,您应该删除整个else
子句。删除其他else { return; }
(对应于$found
为真时),原因相同。
请注意,您的算法具有二次复杂度,对于大输入将会很慢。最好将已使用的记录读入哈希值,然后为CHECKHAIL
的每一行探测%used
哈希以查看它是否已被处理。
删除这些行后,我得到了
$ ./prog.pl 2305 200 2 S SISKIYOU GREENVIEW CA 41.52 -122.9 2 INCH HAIL REPORTED WITH STORM JUST SOUTH OF GREENVIEW. (MFR) 2350 200 DANIELS E FLAXVILLE MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 2350 175 5 N DANIELS RICHLAND MT 48.89 -106.05 DESTROYED CROPS (GGW)
正如您所看到的那样,仍有一个错误。您需要为USEDHAIL
的每一行重新CHECKHAIL
:
seek USEDHAIL, 0, 0 or die "$0: seek: $!";
while(<USEDHAIL>){
...
这会产生
$ ./prog.pl 2350 200 DANIELS E FLAXVILLE MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 2350 175 5 N DANIELS RICHLAND MT 48.89 -106.05 DESTROYED CROPS (GGW)
有关更好方法的示例,请考虑
#! /usr/bin/perl
use warnings;
use strict;
sub read_used_hail {
my($path) = @_;
my %used;
open my $fh, "<", $path or die "$0: open $path: $!";
local $" = " "; # " fix Stack Overflow highlighting
while (<$fh>) {
chomp;
my @f = split " ", $_, 10;
next unless @f;
++$used{"@f"};
}
wantarray ? %used : \%used;
}
my %used = read_used_hail "used-hail";
open my $check, "<", "check-hail" or die "$0: open: $!";
while (<$check>) {
chomp;
my @f = split " ", $_, 10;
next if !@f || $used{join " " => @f};
print $_, "\n";
}
示例运行:
$ ./prog.pl 2350 200 DANIELS E FLAXVILLE MT 48.8 -105.17 GOLF BALL TO HEN EGG SIZED HAIL (GGW) 2350 175 5 N DANIELS RICHLAND MT 48.89 -106.05 DESTROYED CROPS (GGW)
答案 1 :(得分:2)
为什么不为第一个(使用过的)文件创建哈希?
use strict;
use warnings;
my %fromUsedFile;
open USEDFILE, '<', '/the/data/file/that/is/10minutesold';
$fromUsedFile{$_}++ while <USEDFILE>;
close USEDFILE;
while ($toBeChecked = <CHECKHAIL>) {
if (defined $fromUsedFile{$toBeChecked}) {
# ... line is in both the new and old file
} else {
# ... line is only in the new file
$toBeEmailed .= $toBeChecked;
}
}
答案 2 :(得分:1)
在内循环中使用$ _会导致问题。尝试首先命名你的行:
while(my $toBeChecked = <CHECKHAIL>){
my $found = 0;
while( my $hailCheck = <USEDHAIL>){
此外,perl会看到数字比较和字符串比较。您正在使用字符串比较而不是数字比较:
if ($found eq 0){
更改为:
if ($found == 0){
答案 3 :(得分:1)
这条线对我来说很重要:
if ($found eq 0){
由于$found
是布尔值,因此对它执行布尔测试:
if (not $found) {
看起来您的逻辑有点颠倒 - 在第一个if
中,如果行与不匹配则返回,然后在第二个if
中返回,如果有匹配则返回。 你是否打算说next;
跳过最里面的循环呢?