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

7-9 行頭にある最初の擬似括弧の中身を検索

正規表現パズル

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

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

検索前


検索後


対象データ

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


正規表現

^S[^SE]*(?<rec>S[^SE]*\g<rec>[^SE]*E[^SE]*\g<rec>|)[^SE]*E

別解1

^S[^SE]*(?<rec>S[^SE]*\g<rec>E[^SE]*\g<rec>|)[^SE]*E

別解2

^S[^SE]*(?<rec>S[^SE]*\g<rec>E[^SE]*\g<rec>|)E

別解3

^S(?<rec>([^SE]|S\g<rec>E)*)E

別解4

^(?<rec>S([^SE]|\g<rec>)*E)


解説

再帰であっても、
SおよびEの直後に0以上の量指定子があればいいと考えて
別解1,別解2と変形してます。

詳説正規表現3版の472ページからPHPの鬼車でのサンプルがあります。


#Rubyでのソースと実行結果

wStr = '^S[^SE]*(?<rec>S[^SE]*\g<rec>E[^SE]*\g<rec>|)E'
ConstRegex = Regexp.new(wStr)
hairetu = Array.new
hairetu.push('S 1+2+3 E')
hairetu.push('S 1+2+S 3+4 E*5 E+1+2')
hairetu.push('S 1+2+S 3+4 E*5 E+S 1+2 E*3')
hairetu.push('S S S 1+2 E *2 E*3 E+ S1+2 E')
hairetu.push('1+2+S 1*5 E')
hairetu.push('S S E S E E')
hairetu.push('S S S E E S E E')

puts "Pattern #{ConstRegex.source}"
for i in (0..hairetu.length-1)
    willOut = sprintf("Line%02d",i+1) + " #{hairetu[i]} "
    work = ConstRegex.match(hairetu[i]).to_a[0]
    if work then
        willOut += 'matchs ' + work
    else
        willOut += 'no match'
    end
    puts willOut
end

#実行結果
Pattern ^S[^SE]*(?<rec>S[^SE]*\g<rec>E[^SE]*\g<rec>|)E
Line01 S 1+2+3 E matchs S 1+2+3 E
Line02 S 1+2+S 3+4 E*5 E+1+2 matchs S 1+2+S 3+4 E*5 E
Line03 S 1+2+S 3+4 E*5 E+S 1+2 E*3 matchs S 1+2+S 3+4 E*5 E
Line04 S S S 1+2 E *2 E*3 E+ S1+2 E matchs S S S 1+2 E *2 E*3 E
Line05 1+2+S 1*5 E no match
Line06 S S E S E E matchs S S E S E E
Line07 S S S E E S E E matchs S S S E E S E E