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

8-6 括弧問題(組み込みコード)

正規表現パズル

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

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

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

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


正規表現

$c = 0;

m/^S(?{$c++})(?>
                (?(?{$c == 0}) (?!))
                ([^SE]+
                |S(?{$c++})
                |E(?{$c--}))
             )*
 /x


解説

開き括弧である文字Sの数を判定条件とした、
先判定繰り返しを行ってます。

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


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');

for ($i=0; $i <= @hairetu-1; $i++) {
    $LineNo = $i+1;
    $willOut = "Line$LineNo $hairetu[$i] ";

    $c = 0;
if ($hairetu[$i]
   =~ m/^S(?{$c++})(?>
                      (?(?{$c == 0}) (?!))
                      ([^SE]+
                      |S(?{$c++})
                      |E(?{$c--}))
                   )*
       /x){
         $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