2010-05-27 83 views
33

什么是在Perl中搜索匹配字符串的最简单的方法?如何搜索匹配字符串的Perl数组?

一个警告,我想搜索不区分大小写

所以"aAa"将是("aaa","bbb")

+2

你会搜索多少次? – 2010-05-28 02:54:52

+0

它只会被实际搜索一次。运行时复杂性并不是我真正担心的 – Mike 2010-05-28 20:44:14

+1

并不重要,或者与其他任何方式有关,但如果您将数组保存在一组哈希键中(所有值均为'whatever'),您可以查找如果它存在或没有太快,尽管不区分大小写确实会造成问题......哦是的,那个~~ smartmatch的速度可能会很慢...否则,坚持以太的记录良好的答案,证明最简单的答案是“总是最好的答案,即使不是从你的角度来看,也是正确的答案。 – osirisgothra 2015-05-31 10:19:41

回答

26

我猜

@foo = ("aAa", "bbb"); 
@bar = grep(/^aaa/i, @foo); 
print join ",",@bar; 

会做的伎俩。

+8

也许:@bar = grep(/^aaa $/i,@foo); 由于您所写的内容将搜索以/ aaa/i开头的所有字符串,因此它也会找到/ aaaa /和/ aaaa + /。 – 2013-01-23 11:13:10

+0

我认为使用'grep {lc $ _ eq'aaa'},@ foo'会更有效率,从而避免了RegEx处理的需要。 – BlueMonkMN 2015-06-26 18:07:41

+0

所有的都是真实的,并且根据用例非常有效。但我想OP提供的例子只是对他的问题稍有代表性。 – 2015-06-29 12:28:05

5
#!/usr/bin/env perl 

use strict; 
use warnings; 
use Data::Dumper; 

my @bar = qw(aaa bbb); 
my @foo = grep {/aAa/i} @bar; 

print Dumper \@foo; 
131

这取决于你想要搜索的事:

  • ,如果你想找到所有匹配,使用内置grep

    my @matches = grep { /pattern/ } @list_of_strings; 
    
  • 如果你想

    找到第一次匹配,使用first in List::Util

    use List::Util 'first'; 
    my $match = first { /pattern/ } @list_of_strings; 
    
  • ,如果你想找到的所有比赛的计数,使用trueList::MoreUtils

    use List::MoreUtils 'true'; 
    my $count = true { /pattern/ } @list_of_strings; 
    
  • ,如果你想知道指数的第一场比赛的,在List::MoreUtils使用first_index

    use List::MoreUtils 'first_index'; 
    my $index = first_index { /pattern/ } @list_of_strings; 
    
  • 如果你想简单地k现在如果有一个匹配,但你不在乎哪个元素它或它的价值,使用anyList::Util

    use List::Util 1.33 'any'; 
    my $match_found = any { /pattern/ } @list_of_strings; 
    

所有这些例子在他们的核心做类似的事情,但他们的这些实现经过了大量优化,速度很快,并且比使用grep,mapfor loop编写的纯perl实现要快。


请注意,执行循环的算法是一个单独的问题,而不是执行单个匹配。要不区分大小写地匹配一个字符串,您可以简单地使用i标志的模式:/pattern/i。如果您之前没有这样做,您一定要通读perldoc perlre

+0

你假设“匹配”意味着正则表达式匹配,但给出的例子只是(不区分大小写)相等。 – ysth 2010-05-28 04:05:55

+0

我会建议perlretut为初学者,而不是perlre ... – Zaid 2010-05-28 05:21:02

+0

'真'是有点矫枉过正国际海事组织。它比'my $ count = grep {/ pattern /} @list_of_strings;'更快吗? – Zaid 2010-05-28 05:55:04

5

如果你会做许多搜索数组,匹配总是被定义为等价的字符串,那么你就可以标准化您的数据和使用散列。

my @strings = qw(aAa Bbb cCC DDD eee); 

my %string_lut; 

# Init via slice: 
@string_lut{ map uc, @strings } =(); 

# or use a for loop: 
# for my $string (@strings) { 
#  $string_lut{ uc($string) } = undef; 
# } 


#Look for a string: 

my $search = 'AAa'; 

print "'$string' ", 
    (exists $string_lut{ uc $string ? "IS" : "is NOT"), 
    " in the array\n"; 

让我强调一下,如果您计划在数组上进行多次查找,那么做一个哈希查找是很好的。此外,只有在匹配意味着$foo eq $bar或通过规范化才能满足其他要求(如不区分大小写)的情况下,它才会起作用。

28

的Perl 5.10+包含“智能匹配”操作符~~,如果某个元素包含在一个数组或哈希返回true,假如果不(见perlfaq4):

的好处事情是,它也支持正则表达式,这意味着你不区分大小写的要求可以很容易地照顾:

use strict; 
use warnings; 
use 5.010; 

my @array = qw/aaa bbb/; 
my $wanted = 'aAa'; 

say "'$wanted' matches!" if /$wanted/i ~~ @array; # Prints "'aAa' matches!" 
+1

请注意,智能匹配功能是实验性的([source](https://metacpan.org/pod/release/RJBS/perl-5.18.0/pod/perldelta.pod#The-smartmatch-family-of-功能 - 现在是实验)) – 2015-10-23 13:15:04

1

Perl的字符串匹配,也可用于简单的是/否。

my @foo=("hello", "world", "foo", "bar"); 

if ("@foo" =~ /\bhello\b/){ 
    print "found"; 
} 
else{ 
    print "not found"; 
} 
+1

这会在某些情况下导致误报,请考虑例如'我的@foo =(“hello world hello bar”);' – zb226 2014-08-19 13:44:44

+0

关于误报的好的观察。意识到这一点,我发现这对单字测试来说非常简单。如有必要,可以使用连接始终添加分隔符 - 例如,使用\ x01可用于大多数文本字符串。 – 2014-11-26 10:29:26

1

对于刚刚一个布尔匹配结果或发生计数,你可以使用:

use 5.014; use strict; use warnings; 
my @foo=('hello', 'world', 'foo', 'bar', 'hello world', 'HeLlo'); 
my $patterns=join(',',@foo); 
for my $str (qw(quux world hello hEllO)) { 
    my $count=map {m/^$str$/i} @foo; 
    if ($count) { 
     print "I found '$str' $count time(s) in '$patterns'\n"; 
    } else { 
     print "I could not find '$str' in the pattern list\n" 
    }; 
} 

输出:

I could not find 'quux' in the pattern list 
I found 'world' 1 time(s) in 'hello,world,foo,bar,hello world,HeLlo' 
I found 'hello' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo' 
I found 'hEllO' 2 time(s) in 'hello,world,foo,bar,hello world,HeLlo' 

不要求使用的模块。
当然,它不像上面的代码那样“可扩展”和多功能。
我使用这个交互式用户答案来匹配预定义的一组不区分大小写的答案。

相关问题