为什么不返回$ foo if / pattern /;`返回$ foo即使$ foo匹配模式?

时间:2016-09-29 18:59:33

标签: regex perl

我正在使用在 Science 文章中发布的工具,但它给我带来了很多麻烦,因为我对Perl并不熟悉。

代码包含:

return $equa if /\@BOUNDARY/;

我相信代码应该返回$equa,如果它包含文本@BOUNDARY,但它不会这样做。提供的代码是否有错误?

我正在考虑将其更改为:

if ($equa =~ /\@BOUNDARY/) {
    return $equa;
}

这是否执行相同的功能?

作为参考,原始代码中的整个函数是:

sub correctBoundaryReac {
    my $equa = shift;
    print $equa;
    return $equa if /\@BOUNDARY/;
    my( $left, $arrow, $right ) = ( '', '', '' );
    if( $equa =~ /^(<--|<==>|-->) (.+)/ ){
        $arrow = $1;
        $right = $2;
        $left = $right;
        $left =~ s/\@\S+/\@BOUNDARY/g;
    }
    elsif( $equa =~ /(.+) (<--|<==>|-->)$/ ){
        $left  = $1;
        $arrow = $2;
        $right = $left;
        $right =~ s/\@\S+/\@BOUNDARY/g;
    }
    else{
        die "Don't know how to fix bounadry reaction: $equa\n";
    }
    return "$left $arrow $right";
}

3 个答案:

答案 0 :(得分:4)

正如已经解释的那样,if (/$pattern/)表示if ($_ =~ /$pattern/)。见General Variables in perlvar。然后问题是 - 您显示的代码中的$_是什么?

Perl中的许多内置函数和运算符都使用$_作为默认值。但据我所知,子例程不会使用$_@_获取参数,但它是一个完全不同的变量。

但是,在sub的内部,来自sub的封闭范围的$_是可见的

use feature 'say';

sub show_it { say "I see: $_" }

for ('a'..'c') {
    show_it();    # prints with a through c
}

如果这是在您显示的代码中,这意味着子检查变量'@BOUNDARY'中的模式$_ - 但是从调用该子的范围。至少可以说这不是好的做法,并且很容易导致细微的错误。每当调用范围中的代码被更改时,必须检查sub,但我们不会通过sub的接口警告我们($_不是参数)。此外,甚至不需要这个,因为调用代码可以检查和调整该调用。

我宁愿相信你所展示的是一个简单的错误,在这种情况下它应该是

return $equa if $equa =~ /\@BOUNDARY/;

这意味着sub首先检查输入是否已经存在,如果是,它只是返回它。显示的代码的其余部分支持这一点 - 它完全与'@BOUNDARY'

有关

答案 1 :(得分:1)

对于那些没有进入奥术艺术的人来说,这是一种非常不直观的Perl-ism。

Perl有一个所谓的隐藏变量&#34;,$_。本质上,任何带有单个参数的函数调用或这样的比较实际上都会取代$_的值来代替缺失值。例如,

foo() if /bar/;

实际上相当于

if ($_ =~ /bar/) {
    foo();
}

如果您将比较运算符视为函数调用,并且第一个示例具有我之前提到的缺失参数,那么这就很直观。

在您的情况下,如果$_变量的值与相关正则表达式匹配,则代码正在执行的操作是返回某个变量的值。

答案 2 :(得分:1)

return $equa if /\@BOUNDARY/;

的缩写
return $equa if $_ =~ /\@BOUNDARY/;

因此从if语句修饰符转换为if语句会导致

if (/\@BOUNDARY/) {
    return $equa;
}

if ($_ =~ /\@BOUNDARY/) {
    return $equa;
}

但是,您当前的代码很可能是错误的。它表明

return $equa if $equa =~ /\@BOUNDARY/;
应该使用

,在这种情况下使用

完全没问题
if ($equa =~ /\@BOUNDARY/) {
    return $equa;
}