perlサブルーチンの定義を開始する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" であり、必要な 3 行のコメントではありません。正規表現は 3 行すべてのコメントを貪欲に $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.
'