3

我有一个问题,我希望有人能提供帮助(为了解释我想要做什么而大大简化了)......

我有三个不同的数组:

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

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

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

使用数组执行此操作并遍历数组中的每个元素的最佳方法是什么?有没有更好的方法可以做到这一点?

非常感谢您的帮助,谢谢

4

6 回答 6

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
于 2013-04-11T14:16:08.367 回答
2

首先,如果当你发现自己给变量名添加了整数后缀时,认为我应该使用数组

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

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

第三注意,在正则表达式模式中使用 \b 可能会导致令人惊讶的结果。所以,相反,我将把内容分成单独的\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只是循环每个单词集模式。

输出:

---
- 仓鼠:0
- 驴:1
- 大象:2

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

于 2013-04-11T15:40:31.883 回答
2
my $re1 = join '|', @array1;
say "found in array 1" if $variable =~ /$re1/;

Repeat for each additional array (or use an array of regexes and an array of arrays of terms).

于 2013-04-11T13:57:02.633 回答
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

于 2013-04-11T13:54:20.870 回答
0

如果您喜欢使用模块,Regexp::Assemble可能会有所帮助。它允许将正则表达式字符串组合成一个正则表达式,匹配所有单个正则表达式。

于 2013-04-11T14:23:02.187 回答
0

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

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

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

于 2013-04-11T13:56:49.953 回答