我有一个文件,其中包含我需要在给定字符串中匹配的子字符串。这些给定的字符串取自具有实际数据的另一个文件。这是csv文件中的一列。如果给定的字符串具有任何这些子字符串,则它将被标记为TRUE。 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 :(得分:2)
参见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);
答案 1 :(得分:1)
您可以使用selectcol_arrayref或fetchrow_ *和循环来获取要搜索的单词数组。然后通过使用'\ b)|(?:\ b'并使用'(?:\ b'和'\ b)'(或更适合您需要的东西)来连接该数组来构建正则表达式模式。
答案 2 :(得分:1)
这是一些清理过的代码,它们会与您发布的代码执行相同的操作,但在测试之前不会打印$hhfile[10]
以及每个广告模式;如果你需要那个输出,那么你将不得不循环遍历所有模式,并以与你已经做的基本相同的方式单独测试每个模式。 (尽管如此,即使在这种情况下,如果你的循环是for my $count (0 .. $lines)
而不是C风格for (...;...;...)
会更好。)
我没有单独测试每个模式,而是使用Regexp::Assemble,它将构建一个模式,相当于一次测试所有单个子串。 Nikhil Jain的答案中的智能匹配操作符(~~
)在使用时会按照他的答案显示基本相同的东西,但它需要Perl 5.10或更高版本,而Regexp :: Assemble仍然适用于你,如果你'重新开始5.8或(天堂禁止!)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
,代码在语法上是有效的,但尚未经过测试。)