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

7-6 括弧に囲まれたaを検索

正規表現パズル

行頭直後の括弧に囲まれたaを検索する。

検索前


検索後


対象データ

(a)
((a))
(((a)))
((((a))))
a
((a)
(((a)
(((a))
(((((a)))


正規表現

^(?=\()(?<r1>\(\g<r1>\)|a)

別解

^(?<r1>\((a|\g<r1>)\))


解説

まず先読みを除いた下記の正規表現
^(?<r1>\(\g<r1>\)|a)
の再帰について考えて、

再帰レベル0なら ^a
再帰レベル1なら ^(a)
再帰レベル2なら ^((a))
再帰レベル3なら ^(((a)))
再帰レベル4なら ^((((a))))
以下略

といった感じで正規表現を考えると分かりやすいでしょう。

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PL/SQLやC言語の再帰呼び出しと同じく、
リテラルな戻り値がないと
再帰呼び出しが終わらなくなるのと同じ理屈が
田中哲スペシャルの再帰呼び出しでも成立してます。

declare
    function kaijyo(hikiSuu pls_Integer) return pls_Integer is
    begin
        if hikiSuu = 1 then
            return 1;
        else
            return hikiSuu * kaijyo(hikiSuu-1);
        end if;
    end kaijyo;
begin
    DBMS_Output.Put_Line('5の階乗=' || to_char(kaijyo(5)));
    DBMS_Output.Put_Line('8の階乗=' || to_char(kaijyo(8)));
end;
/

5の階乗=120
8の階乗=40320


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

ConstRegex = Regexp.new('^(?<r1>\((a|\g<r1>)\))')
hairetu = Array.new
hairetu.push('(a)')
hairetu.push('((a))')
hairetu.push('(((a)))')
hairetu.push('((((a))))')
hairetu.push('a')
hairetu.push('((a)')
hairetu.push('(((a)')
hairetu.push('(((a))')
hairetu.push('(((((a)))')

puts "Pattern #{ConstRegex.source}"
for i in (0..hairetu.length-1)
    willOut = "Line#{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 ^(?=\()(?<r1>\(\g<r1>\)|a)
Line1 (a) matchs (a)
Line2 ((a)) matchs ((a))
Line3 (((a))) matchs (((a)))
Line4 ((((a)))) matchs ((((a))))
Line5 a no match
Line6 ((a) no match
Line7 (((a) no match
Line8 (((a)) no match
Line9 (((((a))) no match