2010-05-27 78 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' 

不要求使用的模塊。
當然,它不像上面的代碼那樣「可擴展」和多功能。
我使用這個交互式用戶答案來匹配預定義的一組不區分大小寫的答案。