2011-03-14 45 views
0

我有一個文件,其中包含需要在給定字符串中匹配的子字符串。這些給定的字符串取自具有實際數據的另一個文件。這是一個csv文件中的列。如果給定的字符串有任何這些子字符串,它將被標記爲TRUE。什麼是最好的方法是Perl?從Perl中的哈希搜索子字符串匹配

我到目前爲止所做的是這樣的。目前似乎仍然是一些問題:

#!/usr/bin/perl 

use warnings; 
use strict; 

if ($#ARGV+1 != 1) { 
print "usage: $0 inputfilename\n"; 
exit; 
} 

our $inputfile = $ARGV[0]; 
our $outputfile = "$inputfile" . '.ads'; 
our $ad_file = "C:/test/easylist.txt"; 
our %ads_list_hash =(); 

our $lines = 0; 

# Create a list of substrings in the easylist.txt file 
open ADS, "$ad_file" or die "can't open $ad_file"; 
while(<ADS>) { 
     chomp; 
     $ads_list_hash{$lines} = $_; 
     $lines ++; 
} 

for(my $count = 0; $count < $lines; $count++) { 
      print "$ads_list_hash{$count}\n"; 
     } 
open IN,"$inputfile" or die "can't open $inputfile";  
while(<IN>) {  
     chomp;  
     my @hhfile = split /,/;  
     for(my $count = 0; $count < $lines; $count++) { 
      print "$hhfile[10]\t$ads_list_hash{$count}\n"; 

      if($hhfile[9] =~ /$ads_list_hash{$count}/) { 
       print "TRUE !\n"; 
       last; 
      } 
     } 
} 

close IN; 
+0

@Ed我已經把我做的代碼。但是仍然存在一些錯誤。但它有很多錯誤。 – sfactor

回答

1

看到Text::CSV - 逗號分隔值操縱像

use 5.010; 
use Text::CSV; 
use Data::Dumper; 
my @rows; 
my %match; 
my @substrings = qw/Hello Stack overflow/; 
my $csv = Text::CSV->new ({ binary => 1 }) # should set binary attribute. 
       or die "Cannot use CSV: ".Text::CSV->error_diag(); 
open my $fh, "<:encoding(utf8)", "test.csv" or die "test.csv: $!"; 
while (my $row = $csv->getline($fh)) { 
     if($row->[0] ~~ @substrings){ # 1st field 
      say "match " ; 
      $match{$row->[0]} = 1; 
     } 
} 
$csv->eof or $csv->error_diag(); 
close $fh; 
print Dumper(\%match); 
0

您可以使用selectcol_arrayref或fetchrow_ *和循環得到的單詞的數組搜索對於。然後通過將'\ b)|(?:\ b')加入到'(?:\ b'和'\ b)'(或更適合您的需要的東西)來構建正則表達式模式。

0

這裏列出了一些清理後的代碼,它們可以完成與您發佈的代碼相同的功能,除了在測試之前不打印$hhfile[10]以及每個廣告模式;如果您需要該輸出,那麼您將擁有循環遍歷所有模式,並以與您已經完成的方式基本相同的方式單獨測試每個模式(儘管即使在這種情況下,如果您的循環代替C風格也會更好。)

而不是單獨測試每個模式,我用Regexp::Assemble,它將建立一個單一的模式,相當於一次測試所有的單個子串。 Nikhil Jain的答案中的智能匹配運算符(~~)在他的回答中使用時的功能基本相同,但它需要Perl 5.10或更高版本,而如果您使用的是5.8版本,則Regexp :: Assemble仍然適用於您; (天堂禁止!)5.6。

#!/usr/bin/env perl 

use warnings; 
use strict; 

use Regexp::Assemble; 

die "usage: $0 inputfilename\n" unless @ARGV == 1; 

my $inputfile  = $ARGV[0]; 
my $outputfile = $inputfile . '.ads'; 
my $ad_file  = "C:/test/easylist.txt"; 
my @ad_list; 

# Create a list of substrings in the easylist.txt file 
open my $ads_fh, '<', $ad_file or die "can't open $ad_file: $!"; 
while (<$ads_fh>) { 
    chomp; 
    push @ad_list, $_; 
} 

for (@ad_list) { 
    print "$_\n";  # Or just "print;" - the $_ will be assumed 
}  

my $ra = Regexp::Assemble->new; 
$ra->add(@ad_list); 

open my $in_fh, '<', $inputfile or die "can't open $inputfile: $!"; 
while (<$in_fh>) { 
    my @hhfile = split /,/; 
    print "TRUE !\n" if $ra->match($hhfile[9]); 
} 

(代碼在語法上是有效的,根據perl -c,但尚未超出了測試。)