トップページに戻る
次のSQLパズルへ
前のSQLパズルへ
10-203 正規表現の否定先読みを代用
SQLパズル
beforeデータ
---------------------------------------------------
fred this winfred freddies is fred fred record fred
fred fred freddies freddies
fred fred freddy freddies
単語のfredをfreddiesに置換する。
出力結果
-----------------------------------------------------------------------------
before***fred this winfred freddies is fred fred record fred
after****freddies this winfred freddies is freddies freddies record freddies
before***fred fred freddies freddies
after****freddies freddies freddies freddies
before***fred fred freddy freddies
after****freddies freddies freddy freddies
SQL
declare
procedure fred_To_freddies(pstr varchar2) is
willReturn varchar2(4000);
begin
DBMS_Output.Put_Line('before***' || pstr);
willReturn := pstr;
for i in 1..length(pstr)*2 Loop
--for i in 1..length(pstr)*length('freddies')/length('fred') Loop
--willReturn := RegExp_Replace(willReturn, '(^| )fred(dies)?( |$)', '\1freddies\3',i);
willReturn := RegExp_Replace(willReturn, '(^| )fred( |$)', '\1freddies\2',i);
end Loop;
DBMS_Output.Put_Line('after****' || willReturn);
end;
begin
fred_To_freddies('fred this winfred freddies is fred fred record fred');
fred_To_freddies('fred fred freddies freddies');
fred_To_freddies('fred fred freddy freddies');
end;
/
解説
Oracleの正規表現は、11gでも先読みと戻り読みがサポートされてないので、
キャプチャしつつマッチさせて後方参照という方法を使う必要があります。
EmEditorの正規表現なら
((?<=^)|(?<= ))fred(?= |$)
を
freddies
に置換
すればいいです。
■■■■■■■■■■■■■■■■■■■■■■■■■■
RegExp_Replace関数は、
第4引数を指定しても
行頭とみなす位置は変わらないようです。
SQL> select RegExp_Replace('abc','^bc','ZZZ',1) as a,
2 RegExp_Replace('abc','^bc','ZZZ',2) as b,
3 RegExp_Replace('abc','^bc','ZZZ',3) as c,
4 RegExp_Replace('abc','^bc','ZZZ',4) as d,
5 RegExp_Replace('abc','^bc','ZZZ',5) as e
6 from dual;
A B C D E
--- --- --- --- ---
abc abc abc abc abc