簡體   English   中英

使用正則表達式Perl搜索數組

[英]Search array with regex Perl

my @array = ('Joe','Jim','Jim_BOB','Hello');
$search = "Joe";
$search2 = "Hello";
$search3 = "Jim";
$search4 =~ qw/.*?_.*?/;

my %index;
@index{@array} = (0..$#array);
my $index = $index{$search};
my $index2 = $index{$search2};
my $index3 = $index{$search3};
my $index4 = $index{$search4};
print $index,",",$index2,",",$index3,",",$index4, "\n";

這將返回0,3,1,它們是@array中$ search項的索引。 索引無法識別$ search4,但是因為它是一個正則表達式。 我的問題是,如何使用正則表達式搜索@array?

qw用於引用單詞列表,將正則表達式存儲在變量中,最好使用qr

my $search4 = qr/_/; # the leading and trailing '.*?' are redundant 

獲取單個任意匹配索引:

my ($index4) = grep $array[$_] =~ /$search4/, 0..$#array; 

或全部:

my @i = grep $array[$_] =~ /$search4/, 0..$#array;

如果您的數組包含重復元素,則當前使用哈希的方法將僅返回最后一個匹配索引。 其他答案顯示了如何解決現有代碼,但要允許重復的元素,可以使用List::MoreUtils

下面顯示了如何獲取固定搜索字符串和正則表達式的第一個和最后一個匹配索引,以及如何獲取所有匹配索引:

use strict;
use warnings;
use 5.010;

use List::MoreUtils qw(first_index last_index indexes);

my @words = qw(Joe Jim Jim_BOB Hello Jim Hello Jim);

my $string = 'Jim';
my $regex = '^J';

say "First $string: " . first_index { $_ eq $string } @words;
say "Last $string: " . last_index { $_ eq $string } @words;
say "All $string: " . join ', ', indexes { $_ eq $string } @words;

say "First regex: " . first_index { /$regex/ } @words;
say "Last regex: " . last_index { /$regex/ } @words;
say "All regex: " . join ', ', indexes { /$regex/ } @words;

輸出:

First Jim: 1
Last Jim: 6
All Jim: 1, 4, 6
First regex: 0
Last regex: 6
All regex: 0, 1, 2, 4, 6

在您的代碼中存在一個不相關的問題,因為$search4不是一個reqex。 $search4 =~ qw/.*?_.*?/; 表示您正在將未定義的變量$search4qw/.*?_.*?/;相匹配qw/.*?_.*?/; qw基本上是在空格上拆分字符串。 在這種情況下,沒有空格,因此您要匹配字符串.*?_.*? 在無效上下文中,這根本沒有任何作用, $search4定義。

use strict; use warnings; use strict; use warnings; 在聲明變量后,您將得到一個適當的錯誤。

$ cat t1.pl 
use strict;
use warnings;

my @array = ('Joe','Jim','Jim_BOB','Hello');
my $search = "Joe";
my $search2 = "Hello";
my $search3 = "Jim";
my $search4 =~ qw/.*?_.*?/;

my %index;
@index{@array} = (0..$#array);
my $index = $index{$search};
my $index2 = $index{$search2};
my $index3 = $index{$search3};
my $index4 = $index{$search4};
print $index,",",$index2,",",$index3,",",$index4, "\n";

$ perl t.pl 
Use of uninitialized value $search4 in pattern match (m//) at t.pl line 8.
Use of uninitialized value $search4 in hash element at t.pl line 15.
Use of uninitialized value $index4 in print at t.pl line 16.
0,3,1,

我假設您的意思是$search4 = qr/.*?_.*?/

解決您的問題的一種方法是將regexp視為一種特殊情況,並遍歷您的數組。

$ cat t2.pl 
use strict;
use warnings;

my @array = ('Joe','Jim','Jim_BOB','Hello');
my $search = 'Joe';
my $search2 = 'Hello';
my $search3 = 'Jim';
my $search4 = qr/.*?_.*?/;

my %index;
@index{@array} = (0..$#array);
my $index = $index{$search};
my $index2 = $index{$search2};
my $index3 = $index{$search3};

# loop over the array until a match is found
my $cnt = 0;
my $index4;
for my $elem ( @array ) {
    if ( $elem =~ $search4 ) {
        $index4 = $cnt;
        last;
    }
    $cnt++;
}

print "$index,$index2,$index3,$index4\n";

$ perl t2.pl 
0,3,1,2

如果要使用查找哈希,則可能需要CPAN中的模塊Tie :: Hash :: Regex

$ cat t3.pl 
use strict;
use warnings;

# modules from CPAN
use Tie::Hash::Regex;

my @array = ('Joe','Jim','Jim_BOB','Hello');
my $search = "Joe";
my $search2 = "Hello";
my $search3 = "Jim";
my $search4 = qr/.*?_.*?/;

my %index;
tie %index, 'Tie::Hash::Regex';
@index{@array} = (0..$#array);
my $index = $index{$search};
my $index2 = $index{$search2};
my $index3 = $index{$search3};
my $index4 = $index{$search4};
print "$index,$index2,$index3,$index4\n";
bernhard@bernhard-Aspire-E1-572:~/devel/StackOverflow$ perl t3.pl 
0,3,1,2

注意該解決方案有一些缺點。 如果多個鍵匹配,那么您將無法保證獲得哪個匹配鍵。 而且,如果您傳遞的字符串看起來不像正則表達式,則仍將其視為正則表達式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM