有人可以用perl解释我这个正则表达式吗?

时间:2017-05-17 01:38:44

标签: regex perl

有一个使用正则表达式的程序,不知怎的,我无法理解它。

代码+ - 像这样:

@listOfIds = &methodToGetIDs();
foreach my $id (@listOfIds){
    if($class =~ /gen/ig){
        #does stuff
    }
}

我理解的是,如果$class"gen",那么它会进入if{},但有时它会不会进入它,所以我放了一个其他的看到发生了什么,代码最终像这样:

my $class = "genes";
foreach my $id (@listOfIds){
    if($class =~ /gen/ig){
        print $class."\n"; #to see the value of class
    }else{
        print "!!!".$class."\n";   #to see the difference if there's any
    }#miss this wooops!
}
猜猜是什么?输出是这样的:

genes
genes
!!!genes
genes
genes
!!!genes
genes
genes
!!!genes

如果$class的值没有改变那么为什么它会进入else子句?猜猜我根本不理解正则表达式。有线索吗?

2 个答案:

答案 0 :(得分:2)

因为您使用的是/g选项。来自perlop

  

在标量上下文中,m//g的每次执行都会找到下一个匹配项,如果匹配则返回true,如果没有进一步匹配则返回false。可以使用pos()函数读取或设置最后一次匹配后的位置;见pos。失败的匹配通常会将搜索位置重置为字符串的开头,...

所以,你第一次看到这个字符串时会得到一个匹配。然后,下次你在第一场比赛的位置后开始。即该位置不会重置为字符串的开头,而是在第一次匹配发生的位置继续。

/g标志用于表示您希望在字符串中匹配 all 的次数。这对于计算字符串中出现子串的次数很有用。在您的情况下,您正在测试模式是否匹配,是否真实,如果匹配,则执行某些操作。在这种情况下,您不需要/g标志。

my $class = "genes";

foreach my $id (1..6){ 
    if($class =~ /gen/ig){
        print $class."\n"; #to see the value of class
    }else{
        print "!!!".$class."\n";   #to see the difference if there's any
    }
}

输出:

genes                                                                                                                                                                           
!!!genes                                                                                                                                                                        
genes                                                                                                                                                                           
!!!genes                                                                                                                                                                        
genes                                                                                                                                                                           
!!!genes

如果您删除/g标记,则会获得:

genes                                                                                                                                                                           
genes                                                                                                                                                                           
genes                                                                                                                                                                           
genes                                                                                                                                                                           
genes                                                                                                                                                                           
genes

答案 1 :(得分:0)

perlop联机帮助页显示:

  

在标量上下文中,m // g的每次执行都会找到下一个匹配项,   如果匹配则返回true,如果没有进一步匹配则返回false。

由于if评估表达式中标量上下文中的条件,因此每次它首先返回true,然后返回false,因为没有进一步的匹配(我不明白为什么它打印两次,并且你的代码无法编译。)

但请注意:

if ( $class =~ /gen/i ) {

总是在您的示例中为真,因为$class = "genes"并且似​​乎没有变化。您的意思是检查$id吗?

无论如何,/g修饰符似乎不适合您的代码。