2011-03-14 53 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,但尚未超出了测试。)