如何根据正则表达式过滤每个数组元素

时间:2015-11-17 14:23:30

标签: arrays regex perl

我有一个包含这样的元素的数组:

@ORF= (MEZQFVECQWSXC*FVCXRCT*, MAEZCRTDRX*AZEFZC*AZERC*)

我想拆分每个数组,以便每个元素以'M'开头,以'*'结尾,中间没有额外的'*'

所以我上面的例子应该给我

@ORF = (MEZQFVECQWSXC*,MAEZCRTDRX*)

我想过要先拆分这样的每个元素:

    foreach (@ORF) {
        my $true= split /\*/, $_;
        push @ORF, $true
}

然后使用if语句拼接其他人,但这不起作用。

我还考虑过使用grep

@ORF= grep m/M.*\*/, @ORF;

但这不会影响阵列。

我越来越困惑,谷歌没有帮助......请帮帮我?

3 个答案:

答案 0 :(得分:3)

您确实可以使用split和循环执行此操作。您也可以使用map代替for循环。

use strict;
use warnings;
use Data::Printer;

my @ORF= ('MEZQFVECQWSXC*FVCXRCT*', 'MAEZCRTDRX*AZEFZC*AZERC*');
@ORF = map { (split /\*/, $_, 0 )[0] . '*' } @ORF;

p @ORF;

它会遍历@ORF上的split*中的每个元素。 0作为thrid参数告诉split仅拆分一次。将返回值视为一个列表,只取第一个元素([0]),放回星号,你就得到了一个以M开头的新字符串列表,最后以星号。

[
    [0] "MEZQFVECQWSXC*",
    [1] "MAEZCRTDRX*"
]

当然,假设只有符合此模式的字符串而不进行检查。

更简单的方法是使用substrindex来查找*的第一次出现,并将字符串的开头直到该字符。这可能更像你想对splice做的事情,但却误解了它的作用。

@ORF = map { substr $_, 0 , index($_, '*') + 1 } @ORF;

答案 1 :(得分:2)

foreach (@ORF) {
    my $true= split /\*/, $_;
    push @ORF, $true
}

这实际上非常接近解决方案。只有几个问题。

首先,您将split的返回值分配给标量变量。在标量上下文中,split返回它可以将字符串分成的项目数,而不是项目本身。因此,您只需获得值2.我们可以通过将其作为列表分配来解决这个问题。

my ($true) = split /\*/, $_;

其次,您将push新值@ORF发送到@ORF的末尾。这意味着$_只会越来越长,你的循环永远不会结束。您需要使用新值替换数组的当前元素。您可以通过分配到foreach (@ORF) { my ($true) = split /\*/, $_; $_ = "$true*"; } 来完成此操作。

所以整个循环变成:

15 % 7 = 1
21 % 7 = 0
5 % 7 = 5 

说了这么多,我更喜欢simbabque' map solution

答案 2 :(得分:0)

如果你愿意,你也可以使用map + grep,如下所示:

use Data::Dumper;

my @ORF= ("MEZQFVECQWSXC*FVCXRCT*", "MAEZCRTDRX*AZEFZC*AZERC*");
@ORF = grep { $_ =~ /^M/ } map { (split/\*/, $_)[0] . '*' } @ORF;
print Data::Dumper->Dump(\@ORF);

结果:

$VAR1 = 'MEZQFVECQWSXC*';
$VAR2 = 'MAEZCRTDRX*';