使用Perl,如何通过将参数传递给子例程来构建动态正则表达式?

Nic*_*ick 7 regex algorithm perl

我想用动态创建的regxp创建子例程.这是我到目前为止:

#!/usr/bin/perl

use strict;

my $var = 1234567890;


foreach (1 .. 9){
    &theSub($_);
}



sub theSub {
    my $int = @_;
    my $var2 = $var =~ m/(??{$int})/;
    print "$var2\n";
}
Run Code Online (Sandbox Code Playgroud)

看起来它会起作用,但似乎一旦正则表达式中的$ int得到第一次评估,它就永远存在.

反正有没有做类似的事情,但每次调用sub时正则表达式都会获取新的参数?

pts*_*pts 16

修复代码的最简单方法是在括号周围添加括号my,然后删除??{.这是固定的程序:

#!/usr/bin/perl
use strict;
my $var = 1234567890;
foreach (1 .. 9){
    theSub($_);
}
sub theSub {
    my($int) = @_;
    my($var2) = $var =~ m/($int)/;
    print "$var2\n";
}
Run Code Online (Sandbox Code Playgroud)

代码中有问题的一行my $int = @_是等价的my $int = 1,因为它@_在标量上下文中进行了评估,产生了元素的数量@_.要获取sub的第一个参数,请使用my($int) = @_;,@_在列表上下文中计算,或使用获取第一个元素my $int = $_[0];,或使用fetch + remove第一个元素my $int = shift;

在该my $var2 =行中存在类似的问题,您还需要括号来评估列表上下文中的正则表达式匹配,产生列表($1, $2, ...)和分配$var2 = $1.

(??{...})您尝试使用的构造与您想要的构造具有相反的效果:(在做其他事情之间)它在第一次用于匹配时编译了您的正则表达式.对于包含$@不包含??{...}Perl的正则表达式,除非您指定o标志(例如m/$int/o),否则 Perl会自动为每个匹配重新编译正则表达式.

构造(??{...})意味着:使用Perl代码...生成正则表达式,并在此处插入该正则表达式.要获取更多信息,请??{http://perldoc.perl.org/perlre.html上搜索.它在你的例子中不起作用的原因是你需要额外的一层括号来捕获$1,但即使my ($var2) = $var =~ m/((??{$int}))/它没有用,因为它??{有一个未记录的属性:它强制编译它的参数第一个正则表达式用于匹配的时间,因此my ($var2) = $var =~ m/((??{$int + 5}))/总是匹配6.