使用perl循环文件

使用perl循环文件,perl,file,loops,Perl,File,Loops,好的,我有两个文件。一个文件是每10分钟更新一次的数据,而第二个文件是以前使用过的数据。我试图做的是从新文件中取出一行,循环第二个文件的每一行,看看它是否匹配一行。如果是,我不想使用它,但如果没有匹配项,我想将它添加到字符串中。到目前为止,在我所做的工作中,似乎支票从未找到匹配项,即使存在匹配项。下面是我所拥有的,以及我从这两个文件中使用的数据示例。CHECKHAIL和USEDHAIL是两个文件 while(my $toBeChecked = <CHECKHAIL>){

好的,我有两个文件。一个文件是每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;
}
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;
    }
}