我正在用Perl写一个正则表达式来匹配定义Perl子例程的代码。这是我的正则表达式:
my $regex = '\s*sub\s+([a-zA-Z_]\w*)(\s*#.*\n)*\s*\{';
$regex可以匹配启动子程序的代码。我还试图在$1中捕获子程序的名称,在子程序名称和初始大括号之间捕获任何空格和注释并存储在$2中。问题出在$2上。
请考虑以下Perl代码:
my $x = 1;
sub zz
# This is comment 1.
# This is comment 2.
# This is comment 3.
{
$x = 2;
return;
}
当我将这个perl代码放入一个字符串中,然后与$regex匹配时,$2的值是"# This is comment 3.\n",而不是我想要的三行注释。我原以为正则表达式会贪婪地将所有三行注释都放入$2中,但事实并非如此。
我希望了解为什么$regex无法工作,并设计一个简单的替代方法。如下面的程序所示,我有一个更复杂的替换($re3)可以工作。但我认为了解$regex为什么不起作用很重要。
use strict;
use English;
my $code_string = <<END_CODE;
my \$x = 1;
sub zz
# This is comment 1.
# This is comment 2.
# This is comment 3.
{
\$x = 2;
return;
}
END_CODE
my $re1 = '\s*sub\s+([a-zA-Z_]\w*)(\s*#.*\n)*\s*\{';
my $re2 = '\s*sub\s+([a-zA-Z_]\w*)(\s*#.*\n){0,}\s*\{';
my $re3 = '\s*sub\s+([a-zA-Z_]\w*)((\s*#.*\n)+)?\s*\{';
print "\$code_string is '$code_string'\n";
if ($code_string =~ /$re1/) {print "For '$re1', \$2 is '$2'\n";}
if ($code_string =~ /$re2/) {print "For '$re2', \$2 is '$2'\n";}
if ($code_string =~ /$re3/) {print "For '$re3', \$2 is '$2'\n";}
exit 0;
__END__
上述 Perl 脚本的输出如下所示:
$code_string is 'my $x = 1;
sub zz
# This is comment 1.
# This is comment 2.
# This is comment 3.
{
$x = 2;
return;
} # sub zz
'
For '\s*sub\s+([a-zA-Z_]\w*)(\s*#.*\n)*\s*\{', $2 is '# This is comment 3.
'
For '\s*sub\s+([a-zA-Z_]\w*)(\s*#.*\n){0,}\s*\{', $2 is '# This is comment 3.
'
For '\s*sub\s+([a-zA-Z_]\w*)((\s*#.*\n)+)?\s*\{', $2 is '
# This is comment 1.
# This is comment 2.
# This is comment 3.
'
PPI
。例如,$subs=PPI::Document->new(\$code_string)->find('PPI::Statement::Sub');...
- mob