トップページに戻る
次の正規表現パズルへ
前の正規表現パズルへ
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