Perl - 检查每个不同数组中的任何元素是否与变量匹配

时间:2013-04-11 13:51:14

标签: arrays perl loops if-statement www-mechanize

我有一个问题我希望有人可以提供帮助(为了解释我想要做的事情而大大简化了)......

我有三个不同的数组:

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

我还有一个包含网页内容的变量(使用WWW :: Mechanize):

my $variable = $r->content;

我现在想看看每个数组中的任何元素是否都在变量中找到,如果是,那么它来自哪个数组:

e.g

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";
}

使用数组并迭代数组中的每个元素,最好的方法是什么?有没有更好的方法可以做到这一点?

非常感谢您的帮助,谢谢

6 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

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

对每个附加数组重复(或使用正则表达式数组和一组术语数组)。

答案 2 :(得分: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。因此,我将把内容分成\w个字符的单个序列。

第四,你说“我还有一个包含网页内容的变量(使用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中提取给定单词集中的单词。然后,map +{$_ => $i }将这些单词映射到它们来自的单词集。外部map只是循环遍历每个字集模式。

输出:

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

也就是说,你得到一个hashrefs列表,其中每个hashref中的键是找到的单词,值是匹配的单词集。

答案 3 :(得分: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的元素。

答案 4 :(得分:0)

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

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

并对每个数组重复上述操作,即array2,array3 ......

答案 5 :(得分:0)

如果您想使用模块,

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