トップページに戻る    次の正規表現パズルへ    前の正規表現パズルへ

8-5 括弧問題(動的正規表現)

正規表現パズル

行頭直後の開き括弧から、対応する閉じ括弧まで中身を含めて検索する。
括弧のネストは許可する。

擬似括弧として開き括弧をS、閉じ括弧をEとする。

詳説正規表現2版の319ページ
詳説正規表現3版の322ページ
を参考にさせていただきました。

7-9 行頭にある最初の擬似括弧の中身を検索のPerlの動的正規表現を使う解です。


対象データ

S 1+2+3 E
S 1+2+S 3+4 E*5 E+1+2
S 1+2+S 3+4 E*5 E+S 1+2 E*3
S S S 1+2 E *2 E*3 E+ S1+2 E
1+2+S 1*5 E
S S E S E E
S S S E E S E E


正規表現

my $rec;
$rec = qr/(S[^SE]*(??{$rec})E[^SE]*(??{$rec})|)/;

m/^S[^SE]*$rec[^SE]*E/


解説

鬼車での解
^S[^SE]*(?<rec>S[^SE]*\g<rec>E[^SE]*\g<rec>|)E
を流用しています。

バランスしたカッコの正規表現問題


Perlでのソースと実行結果

@hairetu = ();
push(@hairetu,'S 1+2+3 E');
push(@hairetu,'S 1+2+S 3+4 E*5 E+1+2');
push(@hairetu,'S 1+2+S 3+4 E*5 E+S 1+2 E*3');
push(@hairetu,'S S S 1+2 E *2 E*3 E+ S1+2 E');
push(@hairetu,'1+2+S 1*5 E');
push(@hairetu,'S S E S E E');
push(@hairetu,'S S S E E S E E');

my $rec;
$rec = qr/(S[^SE]*(??{$rec})E[^SE]*(??{$rec})|)/;
for ($i=0; $i <= @hairetu-1; $i++) {
    $LineNo = $i+1;
    $willOut = "Line$LineNo $hairetu[$i] ";
    if ($hairetu[$i] =~ m/^S[^SE]*$rec[^SE]*E/){
        $willOut .= "matchs $&";
    }
    else{
        $willOut .= 'no match'
    }
    print "$willOut\n";
}

#実行結果
Line1 S 1+2+3 E matchs S 1+2+3 E
Line2 S 1+2+S 3+4 E*5 E+1+2 matchs S 1+2+S 3+4 E*5 E
Line3 S 1+2+S 3+4 E*5 E+S 1+2 E*3 matchs S 1+2+S 3+4 E*5 E
Line4 S S S 1+2 E *2 E*3 E+ S1+2 E matchs S S S 1+2 E *2 E*3 E
Line5 1+2+S 1*5 E no match
Line6 S S E S E E matchs S S E S E E
Line7 S S S E E S E E matchs S S S E E S E E