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

时间:2009-05-01 05:46:34

标签: regex perl algorithm

我想用动态创建的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";
}

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

无论如何都要做类似的事情,但每次调用sub时正则表达式会选择新的参数吗?

4 个答案:

答案 0 :(得分: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";
}

代码中有问题的一行是my $int = @_,相当于my $int = 1,因为它在标量上下文中评估了@_,产生了{{1}中的元素数量}。要获取sub的第一个参数,请使用@_来评估列表上下文中的my($int) = @_;,或使用@_获取第一个元素,或使用{{1获取+删除第一个元素}}

my $int = $_[0];行中存在类似的问题,您还需要括号来评估列表上下文中的正则表达式匹配,产生my $int = shift;列表,并指定my $var2 =

你试图使用的构造($1, $2, ...)产生与你想要的相反的效果:(在做其他事情之间)它在第一次用于匹配时编译你的正则表达式。对于包含$var2 = $1(??{...})但未包含$的正则表达式,Perl会自动为每个匹配重新编译正则表达式,除非指定@标志(例如??{...})。

构造o表示:使用Perl代码m/$int/o生成正则表达式,并在此处插入该正则表达式。要获取更多信息,请在http://perldoc.perl.org/perlre.html上搜索(??{...})。它在您的示例中不起作用的原因是您需要额外的一层括号来捕获...,但即使使用??{也不会有效,因为{{1} }具有未记录的属性:它在第一次使用正则表达式进行匹配时强制编译其参数,因此$1始终匹配my ($var2) = $var =~ m/((??{$int}))/

答案 1 :(得分:3)

my $int = @_;

这将为您提供参数计数,在您的情况下始终为“1”。

我想你想要

my $int = shift;

答案 2 :(得分:3)

要动态地将正则表达式传递给函数,而不是在函数中动态构建它,请使用qr //.

#!/usr/bin/perl

use strict;

my $var = 1234567890;


foreach (1 .. 9){
    &theSub(qr/$int/);
}



sub theSub {
    my($regexp) = @_;
    my($var2) = ($var =~ $regexp);
    print "$var2\n";
}

qr //接受与m //相同的尾随参数:i,m,s和x

答案 3 :(得分:0)

我的$ int是标量上下文,他有($ int)列表上下文,并将$ _ [0]放入$ int。在下文中,只有10个被放入$ int,其余的11到99个被丢失。

my($ int)=(10..99); print $ int; 10

相关问题