2013-04-11 56 views
2

我有一个问题,我希望有人能(大大简化解释什么,我试图做的目的)帮助...的Perl - 检查是否在每个不同阵列的所有元素相匹配的可变

我有三种不同的阵列:

my @array1 = ("DOG","CAT","HAMSTER"); 
my @array2 = ("DONKEY","FOX","PIG", "HORSE"); 
my @array3 = ("RHINO","LION","ELEPHANT"); 

我也有一个包含从网页内容的变量(使用WWW ::机械化):

my $variable = $r->content; 

我现在想看看是否有任何元素在每个阵列在变量中,如果是这样,其阵列它来源于:

if ($variable =~ (any of the elements in @array1)) { 
    print "FOUND IN ARRAY1"; 
} elsif ($variable =~ (any of the elements in @array2)) { 
    print "FOUND IN ARRAY2"; 
} elsif ($variable =~ (any of the elements in @array3)) { 
    print "FOUND IN ARRAY3"; 
} 

什么是去这样做使用阵列,通过在每个元素进行迭代的最佳方法数组?有没有更好的办法可以做到这一点?

您的帮助深表感谢,感谢

回答

7

你可以做一个正则表达式出数组的元素,但你很可能要禁用元字符确保你没有得到部分匹配:

my $rx = join('\b|\b', map quotemeta, @array1); 

if ($variable =~ /\b$rx\b/) { 
    print "matched array 1\n"; 
} 

如果你想获得部分匹配,如下面的FOXY,只需删除所有的\b序列。

示范:

use strict; 
use warnings; 

my @array1 = ("DOG","CAT","HAMSTER"); 
my @array2 = ("DONKEY","FOX","PIG", "HORSE"); 
my @array3 = ("RHINO","LION","ELEPHANT"); 

my %checks = (
    array1 => join('\b|\b', map quotemeta, @array1), 
    array2 => join('\b|\b', map quotemeta, @array2), 
    array3 => join('\b|\b', map quotemeta, @array3), 
); 

while (<DATA>) { 
    chomp; 
    print "The string: '$_'\n"; 
    for my $key (sort keys %checks) { 
     print "\t"; 
     if (/\b$checks{$key}\b/) { 
      print "does"; 
     } else { 
      print "does not"; 
     } 
     print " match $key\n"; 
    } 
} 

__DATA__ 
A DOG ATE MY RHINO 
A FOXY HORSEY 

输出:如果你喜欢使用一个模块

The string: 'A DOG ATE MY RHINO' 
     does match array1 
     does not match array2 
     does match array3 
The string: 'A FOXY HORSEY' 
     does not match array1 
     does not match array2 
     does not match array3 
+0

把\ b放在连接中会禁用aho-corasick匹配,我相信;只要做'\ b(?:$ rx)\ b'而不是 – ysth 2013-04-12 19:47:03

+0

@ysth Aho是什么?那是什么英文? – TLP 2013-04-12 19:49:06

+0

perl有时会用于|的匹配算法交替固定的字符串;没有它,基本上每个|替代方法将在字符串中的每个位置进行尝试,直到匹配成功。 http://en.wikipedia.org/wiki/Aho-Corasick – ysth 2013-04-12 20:33:54

0

编辑:我想你可以使用Perl的map功能,这样的事情:

@a1matches = map { $variable =~ /$_/ ? $_ :(); } @array1; 
print "FOUND IN ARRAY1\n" if $#a1matches >= 0; 

@a2matches = map { $variable =~ /$_/ ? $_ :(); } @array2; 
print "FOUND IN ARRAY2\n" if $#a2matches >= 0; 

@a3matches = map { $variable =~ /$_/ ? $_ :(); } @array3; 
print "FOUND IN ARRAY3\n" if $#a3matches >= 0; 

一个有趣的副作用是@a1matches包含@array1的元素在$variable

+1

除非'$ variable'包含一个假值,否则永远不会返回false。而且,你的支票也是相反的。 – TLP 2013-04-11 13:55:30

+2

你有它倒退。他想知道是否有任何数组元素在'$ variable'中,而不是'$ variable'是否在任何数组中。 – 2013-04-11 13:55:30

+0

糟糕。让我在这里思考和编辑答案。 – 2013-04-11 13:56:13

0

我假设$variable不是数组,在这种情况下使用foreach语句。

foreach my $item (@array1) { 
    if ($item eq $variable) { 
     print "FOUND IN ARRAY1"; 
    } 
} 

并重复上述为每个阵列,即数组2,ARRAY3 ...

2
my $re1 = join '|', @array1; 
say "found in array 1" if $variable =~ /$re1/; 

重复对其他每个阵列(或使用正则表达式的阵列,并且术语的数组的数组)。

+0

@array的内容之一有特殊字符,如'| | “? – imran 2013-04-11 14:03:58

+0

@imran:在这种情况下,'my $ re1 = join'|',map {“\ Q $ _ \ E”} @ array1;' – 2013-04-11 14:06:14

+1

您还必须担心部分匹配。 – TLP 2013-04-11 14:06:52

0

Regexp::Assemble可能会有所帮助。它允许将正则表达式的字符串组合成一个匹配所有单个正则表达式的正则表达式。

1

首先,如果When you find yourself adding an integer suffix to variable names, think I should have used an array

因此,首先我要将wordsets放入arrayrefs数组中。这将有助于确定匹配的单词来自哪里。

其次,我打算使用Regex::PreSuf从每个单词列表中创建一个模式,因为我总是忘记了正确的方法。

第三个注意事项是using \b in regex patterns can lead to surprising results。所以,相反,我将把内容分解成单个的字符序列。第四,你说“我也有一个包含网页内容的变量(使用WWW :: Mechanize)”。你想在评论中匹配单词吗?在title属性?如果您不这样做,则应解析HTML文档以提取完整纯文本或将匹配限制在特定元素或元素集内。

然后,grep从文本中的单词列表中找到单词集中的单词,并将它们映射到它们匹配的单词集。

#!/usr/bin/env perl 

use strict; use warnings; 

use Regex::PreSuf qw(presuf); 

my @wordsets = (
    [ qw(DOG CAT HAMSTER) ], 
    [ qw(DONKEY FOX PIG HORSE) ], 
    [ qw(RHINO LION ELEPHANT) ], 
); 

my @patterns = map { 
    my $pat = presuf(@$_); 
    qr/\A($pat)\z/; 
} @wordsets; 

my $content = q{Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim 
ad minim veniam, quis ELEPHANT exercitation ullamco laboris nisi ut aliquip 
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in HAMSTER 
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat 
cupidatat non proident, sunt in DONKEY qui officia deserunt mollit anim id 
est laborum.}; 

my @contents = split /\W+/, $content; 

use YAML; 
print Dump [ 
    map { 
     my $i = $_; 
     map +{$_ => $i }, 
     grep { $_ =~ $patterns[$i] } @contents 
    } 0 .. $#patterns 
]; 

这里,grep { $_ =~ $patterns[$i] } @contents提取从@contents这是在给定的wordset词语的然后,map +{$_ => $i }将这些单词映射到它们来自的单词集。外部map只是循环每个单词模式。

输出:

--- 
- HAMSTER: 0 
- DONKEY: 1 
- ELEPHANT: 2

也就是说,你得到hashrefs的一个列表,其中每个hashref关键的是,被发现字和值是相匹配的wordset。

相关问题