2010-07-28 102 views
0

好吧我有2个文件。一个文件是每10分钟更新一次的数据,而另一个文件是之前使用过的数据。我想要做的是从新文件中取一行,然后循环遍历第二个文件的每一行,看它是否与一行匹配。如果是这样,我不想使用它,但如果没有匹配比我想将它添加到字符串。在我迄今为止所做的事情看来,即使有支票,支票也找不到匹配。这里是我所拥有的和我从这两个文件中使用的数据样本。 CHECKHAIL和USEDHAIL是两个文件通过Perl文件循环访问

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

这听起来像是一个强大的坏主意,并且任务的复杂性将由O(n ** 2)完成。只需将数据放在数据库中,为任何定义的主键约束添加UNIQUE,添加另一列'date_entered DEFAULTS CURRENT_TIMESTAMP',然后选择'date_entered> TODAY - '1 day':: interval'。 – 2010-07-28 20:11:25

回答

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; 
    } 
} 
+0

因为我不知道如何创建一个散列。我会尝试这个,虽然 – shinjuo 2010-07-28 20:47:55

+0

这是给我的$ usedFileName和$ fromUSedFile语法错误。我应该做些什么声明 – shinjuo 2010-07-28 21:04:20

+0

@shinjuo - 答案已更新,可以在启用“strict”的情况下更加开放。 – mob 2010-07-28 21:14:14

1

使用$ _的内部循环中可能会出现问题。尝试命名您的行首先是这样的:

while(my $toBeChecked = <CHECKHAIL>){ 
    my $found = 0; 
    while(my $hailCheck = <USEDHAIL>){ 

此外perl看到数值比较和字符串比较不同。您使用的字符串比较,而不是数字比较:

if ($found eq 0){ 

更改为:

if ($found == 0){ 
+0

这是非常有用的知道,但我仍然得到同样的问题 – shinjuo 2010-07-28 19:51:14

+1

看到我刚刚发布的编辑 – Cfreak 2010-07-28 19:52:36

+0

我didnt知道,但仍然不工作 – shinjuo 2010-07-28 19:53:37

1

此行伸出我:

if ($found eq 0){ 

由于$found是一个布尔值,执行布尔测试:

if (not $found) { 

它也看起来像你的逻辑有点逆转 - 在第一个if,你返回,如果行不匹配,然后在第二个if,你返回,如果有匹配。 您是否打算说next;跳过最内层循环?

+0

仍然无法正常工作。你的意思是如果($ found){ }然后把连接放在} else {part?那就是我试过的 – shinjuo 2010-07-28 19:57:00

+0

我甚至不需要第一个其他的东西,我只想测试它是否匹配。 – shinjuo 2010-07-28 20:07:20

3

它永远不会有机会成功,因为

while(<USEDHAIL>){ 
    my $hailCheck = $_; 
    if($toBeChecked eq $hailCheck){ 
     $found += 1; 
    }else{ 
     return; ### XXX 
    } 
} 

在第一个不匹配,子返回到它的调用者。您可能的意思是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)

正如你所看到的,仍然有一个错误。您需要倒带USEDHAILCHECKHAIL每一行:

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 [email protected] || $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)
+0

我会在哪里放置我的文件路径。如果你不能说,我对perl相当陌生,其中一些是我从未用过的东西。 – shinjuo 2010-07-28 20:19:43

+0

上面的代码为您的两个输入文件拼凑了无法想象的名称'check-hail'和'used-hail'。 – 2010-07-28 20:23:19

+0

我上面使用的编辑过的代码是我尝试过的,但它仍然不起作用。我现在要试着去处理你刚刚给我的东西,看看它会发生什么。 – shinjuo 2010-07-28 20:37:47