简体   繁体   English

Perl,将标量与数组进行比较(使用正则表达式?)

[英]Perl, comparing scalar to array (with regex?)

I'll be brief so I don't waste your time; 我会简短,所以我不浪费你的时间;

Simple problem, i have an array of say, hundreds of dogs 简单的问题,我有一堆说,数百只狗

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull ...)

and i want to compare it to a single dog 我想把它与一只狗比较

my $doggy = "Shepard";

pretty stupid i know, but how would i do that? 我知道这很愚蠢,但我怎么办呢?

# Regex match against array?
# (This doesnt even work but its how i would think of doing it)
if ($doggy =~ /@dogs/) {
print $doggy;
}

Thanks for any answers in advance, I appreciate you guys helping me with what is probably a really stupid question. 在此先感谢您的任何答案,我感谢你们帮助我解决可能是一个非常愚蠢的问题。 Thank you 谢谢

I would do it like this : 我会这样做:

my %hDogs = map { $_ => 1 } @dogs;

if(exists($hDogs{$doggy})) { ... }

You can just use grep: 你可以使用grep:

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull);
my @wanted_dogs = grep {/^Shepard$/} @dogs;
print "@wanted_dogs\n";

Result: 结果:

Shepard

The regex can be changed as wanted, and if you're only interested in the first matching dog, you'll find that in $wanted_dogs[0] . 正则表达式可以根据需要进行更改,如果您只对第一个匹配的狗感兴趣,您可以在$wanted_dogs[0]找到它。

Smart match operator : 智能匹配运营商

use warnings;
use strict;

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull);
my $doggy = "Shepard";
if ($doggy ~~ @dogs) {
    print $doggy;
}

Assuming you don't really want a regular expression match and just want to see if there is an exact match somewhere in the list, then you have a number of options. 假设你真的不想要正则表达式匹配,只想查看列表中某处是否存在完全匹配,那么你有很多选择。

Smart match is the relatively new, but simplest and possibly fastest approach. 智能匹配是一种相对较新,但最简单且可能最快的方法。

The classic methods are grep and List::Util::first . 经典的方法是grepList :: Util :: first You can adjust the latter two to use a regex instead of eq if you do want to (for example) match "Shepard" when $dog is "Shep". 如果你想(例如)当$dog是“Shep”时匹配“Shepard”,你可以调整后两个使用正则表达式而不是eq

use strict;
use warnings;
use v5.10;

my @dogs = qw(Shepard Lab Dalmation Husky Chow Pitbull);
my $dog = "Shepard";
my $cat = "Ocicat";

say "Smart match";
say $dog ~~ @dogs;
say $cat ~~ @dogs;

say "Grep";
say grep { $_ eq $dog } @dogs;
say grep { $_ eq $cat } @dogs;

say "List::Util";
use List::Util qw/first/;
say first { $_ eq $dog } @dogs;
say first { $_ eq $cat } @dogs;

There are techniques using the newer smart-match operator, but I prefer the old classic: 有一些技术使用较新的智能匹配运算符,但我更喜欢旧的经典:

my $dogs_re = join '|' => map quotemeta, @dogs;

if ($doggy =~ /$dogs_re/) {...}

That creates a regex alternation of your dog types, after quoting any regex special characters in the names. 在引用名称中的任何正则表达式特殊字符后,这将创建您的狗类型的正则表达式替换。

You could compile the regex as well if you want: 如果需要,您也可以编译正则表达式:

$_ = qr/$_/ for $dogs_re;  

which would be placed after the line defining $dogs_re, and may offer some performance benefits if you will be using the regex many times. 它将放在定义$ dogs_re的行之后,并且如果您将多次使用正则表达式,可能会提供一些性能优势。

I would probably choose the hash lookup solution for best answer, but there are many ways to do this. 我可能会选择哈希查找解决方案以获得最佳答案,但有很多方法可以做到这一点。 This is one of them. 这是其中之一。

Note that this uses our dog name as the regex and iterates it over the list instead of the other way around. 请注意,这使用我们的狗名称作为正则表达式并在列表上迭代它而不是相反。

use v5.10; # needed for say
@dogs=qw(Shepherd Lab Poodle Foo Bar); 
$dog = 'Lab'; 
/\Q$dog\E/i and say for @dogs;"

You can control how strict the match is: 您可以控制匹配的严格程度:

/\\Q$dog\\E/i is least strict, ignore case, match anywhere in word. /\\Q$dog\\E/i最不严格,忽略大小写,匹配任何单词。 Eg "lab" will match "Yellow Lab", "Labrador" etc. 例如“实验室”将匹配“黄色实验室”,“拉布拉多”等。

/^\\Q$dog\\E$/ is most strict, match case, match entire word. /^\\Q$dog\\E$/是最严格的,匹配大小写,匹配整个单词。

Try this, 尝试这个,

$" = "|";
my @dogs=qw(Shepherd Lab Poodle Foo Bar);
my $temp = "@dogs";
my $dog = "Lab";
print "$1 found" if ($dog =~ /($temp)/);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM