2013-04-11 43 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。

相關問題