使用perl循环文件
好的,我有两个文件。一个文件是每10分钟更新一次的数据,而第二个文件是以前使用过的数据。我试图做的是从新文件中取出一行,循环第二个文件的每一行,看看它是否匹配一行。如果是,我不想使用它,但如果没有匹配项,我想将它添加到字符串中。到目前为止,在我所做的工作中,似乎支票从未找到匹配项,即使存在匹配项。下面是我所拥有的,以及我从这两个文件中使用的数据示例。CHECKHAIL和USEDHAIL是两个文件使用perl循环文件,perl,file,loops,Perl,File,Loops,好的,我有两个文件。一个文件是每10分钟更新一次的数据,而第二个文件是以前使用过的数据。我试图做的是从新文件中取出一行,循环第二个文件的每一行,看看它是否匹配一行。如果是,我不想使用它,但如果没有匹配项,我想将它添加到字符串中。到目前为止,在我所做的工作中,似乎支票从未找到匹配项,即使存在匹配项。下面是我所拥有的,以及我从这两个文件中使用的数据示例。CHECKHAIL和USEDHAIL是两个文件 while(my $toBeChecked = <CHECKHAIL>){
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;
}
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)
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)
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)
在内部循环中使用$可能会导致问题。尝试先命名您的行,如下所示:
while(my $toBeChecked = <CHECKHAIL>){
my $found = 0;
while( my $hailCheck = <USEDHAIL>){
改为:
if ($found == 0){
这句话很适合我:
if ($found eq 0){
由于$found是布尔值,请对其执行布尔测试:
if (not $found) {
看起来您的逻辑也有点颠倒-在第一个if中,如果行不匹配,则返回,然后在第二个if中,如果存在匹配,则返回。你是否打算接着说;要跳出最内部的循环,它永远没有机会成功,因为
while(<USEDHAIL>){
my $hailCheck = $_;
if( $toBeChecked eq $hailCheck){
$found += 1;
}else{
return; ### XXX
}
}
正如您所看到的,它仍然有一个bug。您需要为每行支票倒带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)
为什么不为第一个使用的文件创建一个散列呢
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;
}
}
这是非常有帮助的知道,但我仍然得到同样的问题也,你确定线是完全相同的吗?如果我只是从一个文件复制并粘贴到另一个文件,那么如果它是一个特殊的空白,制表符为一个,那么它并不总是正确复制。将一个文件复制到两个新文件中,并使用这些文件进行检查和使用。仍然不工作。你的意思是如果$find{然后把concatation放在}else中吗{part?这就是我想做的,我甚至不需要第一个,事实上,我只是想测试它是否匹配。这听起来是一个非常糟糕的主意,任务的复杂性将在**2上增加。只需将数据放入数据库中,在定义为唯一的数据上添加主键约束,添加另一列日期\输入默认值\当前时间戳,然后选择您输入的日期>今天-'1天'::interval.我应该把我的文件路径放在哪里。如果您不知道,我对perl非常陌生,其中一些是我从未使用过的东西。上面的代码对缺乏想象力的名称进行硬编码检查hail,并对您的两个输入文件使用hail。我上面使用的编辑代码就是我尝试过的代码,并且它可以d仍然不起作用。我现在将尝试使用您刚才给我的代码,看看它的用途。请注意,我上面发布的代码有什么问题。它看起来像您使用的代码,但仍然不起作用?如果$toBeChecked eq$hailCheck,您的更新代码应该有{而不是==因为您正在比较字符串。若要将记录附加到所用文件的结尾,请确保以读取和附加模式打开它,例如,打开USEDHAIL、>>+、$path,并且不要忘记在所有读取之前查找开头。因为我不知道如何创建哈希。我会尝试这种方法,因为这会给我$u的语法错误sedFileName和$fromUSedFile。我应该用什么声明those@shinjuo-答案已更新,可以在启用strict的情况下进行更多的开箱即用。这非常有效。我感谢您的帮助。我仍在阅读perl O'Reilly的学习书籍,因此我希望很快就能接触到Hash
#! /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)
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;
}
}