Поиск совпадения подстроки из хэша в Perl - PullRequest
1 голос
/ 14 марта 2011

У меня есть файл, который содержит подстроки, которые мне нужно сопоставить в данной строке.Эти данные строки взяты из другого файла, который содержит фактические данные.Это столбец в CSV-файле.Если в данной строке есть какая-либо из этих подстрок, она будет помечена как ИСТИНА.Какой лучший способ сделать это - 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;

Ответы [ 3 ]

2 голосов
/ 14 марта 2011

см. 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 голос
/ 14 марта 2011

Вот некоторый очищенный код, который будет делать то же самое, что и код, который вы опубликовали, за исключением того, что он не печатает $hhfile[10] вместе с каждым шаблоном рекламы перед их тестированием; если вам нужен этот вывод, то вам придется пройтись по всем шаблонам и протестировать каждый из них в основном так же, как вы уже это делали. (Хотя даже в этом случае было бы лучше, если бы ваши циклы были for my $count (0 .. $lines) вместо стиля C * for (...;...;...).)

Вместо того, чтобы тестировать каждый шаблон отдельно, я использовал Regexp :: Assemble , который создаст один шаблон, что эквивалентно тестированию всех отдельных подстрок одновременно. Оператор умного совпадения (~~) в ответе Нихила Джайна будет использовать в основном то же самое при использовании, как показано в его ответе, но для этого потребуется 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, но после этого не тестировался.)

1 голос
/ 14 марта 2011

Вы можете использовать selectcol_arrayref или fetchrow_ * и цикл, чтобы получить массив слов для поиска.Затем создайте шаблон регулярного выражения, соединив этот массив с '\ b) | (?: \ B' и включив в него '(?: \ B' и '\ b)' (или что-то более подходящее для ваших нужд).

...