2017-06-14 14 views
4

単語OFのインスタンスを "OF"に置き換えたいとします。私は完全な言葉でこれを働かせたいだけです。 L_OF、DOF、OFZ、DOFD、OF_Lなどではありません。Oracle regexp_replace on complete words

私のコードは、最後の文字列を除き、以下のように動作します。

それを返します:

("OF"*OF + 2) 

を...代わりに:

("OF"*"OF" + 2) 

私はそれは同様にその1つの上で動作するように取得できますか?

with stg as 
(
select '(ofof+ol)' str from dual union all 
select '(oof+ol+of)' from dual union all 
select '(*of + 2)'  from dual union all 
select '(of*of + 2)' from dual 
) 
select str, 
     regexp_replace(upper(str), '(\W|^)(OF)(\W|$)', '\1"OF"\3') as str2 
from stg 
+0

問題は、posix正規表現のルックアラウンドの欠如です。私はあなたがplsqlプロシージャに入れ、regexp_replaceをラウンドしたりネストしたり、別の置換で余分な引用符を削除したりしなければならないものを得たいと思っています。 – RLOG

答えて

0

これはコメントには長すぎます。私は解決策を知らないが、私は問題を理解している。 'of of'ではもっと簡単に表示されますが、'of**of'では表示されません。

問題は、最初の単語を定義する文字は、2番目の単語を定義するために使用されないということです。正規表現には、 "前一致後の最初の文字"を意味する "^"などの特殊文字が必要です。私は1つが存在するかどうかわからない。

3

これを行う方法の1つは、再帰的なクエリです(Oracle 11.2以降が必要です)。それが速いと期待しないでください。

with stg as 
(
    select '(ofof+ol)' str from dual union all 
    select '(oof+ol+of)' from dual union all 
    select '(*of + 2)'  from dual union all 
    select '(of*of + 2)' from dual 
), 
rec (str, lvl, new_str) as 
(
    select str, 1, upper(str) 
    from stg 
    union all 
    select str, lvl + 1, 
     regexp_replace(new_str, '(\W|^)(OF)(\W|$)', '\1"OF"\3', 1, lvl) 
    from rec 
    where regexp_instr(new_str, '(\W|^)(OF)(\W|$)', 1, lvl) > 0 
) 
select str, new_str 
from rec 
where regexp_instr(new_str, '(\W|^)(OF)(\W|$)', 1, lvl) = 0 
; 

STR   NEW_STR   
------------ ------------------ 
(ofof+ol) (OFOF+OL)   
(oof+ol+of) (OOF+OL+"OF")  
(*of + 2) (*"OF" + 2)  
(of*of + 2) ("OF"*"OF" + 2) 
+0

ありがとう - それは素晴らしい作品です! –