Oracle REGEXP_REPLACE 字符串从 nn 位置开始替换 'n' 次
Oracle REGEXP_REPLACE string to replace 'n' times starting with nn position
我想替换'|'和 '_'。替换应该从第nn个字符开始,替换n次。例如
ABC|1234|mno|p|q|r|456|XYZ|QRS|TUV ====> ABC|1234|mno|p_q_r|456|XYZ|QRS|TUV
在上面的例子中 nn=14 和 n=3
到目前为止,我已经试过了,但没有得到预期的结果
SELECT REGEXP_REPLACE('ABC|1234|mno|p|q|r|456|XYZ', '[|]', '_',14) rep_str FROM DUAL
您可以使用普通 substr
/instr
来完成,但需要仔细处理边缘情况。提取您需要的部分并更换其中的所有管道。然后把所有东西都放在一起。
with
--
function replace_n(
str in varchar2,
start_ in number,
count_ in number
)
return varchar2
as
begin
return
/*Starting part unchanged*/
substr(str, 1, start_)
/*Replacement: locate n'th - 1 occurrence of pipe*/
|| translate(
substr(str, start_ + 1, instr(str, '|', start_, count_-1) - start_)
, '|'
, '_'
)
/*Remaining string*/
|| substr(str, instr(str, '|', start_, count_ - 1) + 1)
;
end;
--
a(a) as (
select
'ABC|1234|mno|p|q|r|456|XYZ|QRS|TUV'
from dual
)
select replace_n(a, 14, 3) as res
from a
| RES |
| :--------------------------------- |
| ABC|1234|mno|p_q_r|456|XYZ|QRS|TUV |
db<>fiddle here
UPD:或者如果您要从位置 nnn
:
开始替换大小为 n
的子字符串
with
--
function replace_n(
str in varchar2,
start_ in number,
count_ in number
)
return varchar2
as
begin
return
/*Starting part unchanged*/
substr(str, 1, start_)
/*Replacement: extract substring on size n*/
|| translate(
substr(str, start_ + 1, instr(str, '|', start_, count_-1) - start_)
, '|'
, '_'
)
/*Remaining string*/
|| substr(str, instr(str, '|', start_, count_ - 1) + 1)
;
end;
--
db<>fiddle here
在您的简单示例中,更容易指定两个事件:
regexp_replace(
str
, '\|([^|]+)'
||'\|([^|]+)' -- 2 times just to make it more readable
||'(.*)' -- others
,'__'
,14
)
带有测试数据的完整示例:DBFiddle
with t as (
select
'ABC|1234|mno|p|q|r|456|XYZ|QRS|TUV' str
,'ABC|1234|mno|p_q_r|456|XYZ|QRS|TUV' chk
from dual
)
select
str,chk,
regexp_replace(
str
, '\|([^|]+)'
||'\|([^|]+)' -- 2 times just to make it more readable
||'(.*)' -- others
,'__'
,14
) as str2
from t
/
或者如果你让它更可定制并更容易指定替换数量,你可以使用简单的内联 pl/sql 函数和这样的循环:DBFiddle
with function regexp_replaces(
source_char varchar2
,pattern varchar2
,replace_char varchar2
,position int
,cnt int
) return varchar2
as
res varchar2(4000):=source_char;
begin
for i in 1..cnt loop
res:=regexp_replace(res,pattern,replace_char,position,1);
end loop;
return res;
end;
select
str,chk,
regexp_replaces(str,'\|','_',14,2) as str2
from t;
我想替换'|'和 '_'。替换应该从第nn个字符开始,替换n次。例如
ABC|1234|mno|p|q|r|456|XYZ|QRS|TUV ====> ABC|1234|mno|p_q_r|456|XYZ|QRS|TUV
在上面的例子中 nn=14 和 n=3
到目前为止,我已经试过了,但没有得到预期的结果
SELECT REGEXP_REPLACE('ABC|1234|mno|p|q|r|456|XYZ', '[|]', '_',14) rep_str FROM DUAL
您可以使用普通 substr
/instr
来完成,但需要仔细处理边缘情况。提取您需要的部分并更换其中的所有管道。然后把所有东西都放在一起。
with -- function replace_n( str in varchar2, start_ in number, count_ in number ) return varchar2 as begin return /*Starting part unchanged*/ substr(str, 1, start_) /*Replacement: locate n'th - 1 occurrence of pipe*/ || translate( substr(str, start_ + 1, instr(str, '|', start_, count_-1) - start_) , '|' , '_' ) /*Remaining string*/ || substr(str, instr(str, '|', start_, count_ - 1) + 1) ; end; -- a(a) as ( select 'ABC|1234|mno|p|q|r|456|XYZ|QRS|TUV' from dual ) select replace_n(a, 14, 3) as res from a
| RES | | :--------------------------------- | | ABC|1234|mno|p_q_r|456|XYZ|QRS|TUV |
db<>fiddle here
UPD:或者如果您要从位置 nnn
:
n
的子字符串
with -- function replace_n( str in varchar2, start_ in number, count_ in number ) return varchar2 as begin return /*Starting part unchanged*/ substr(str, 1, start_) /*Replacement: extract substring on size n*/ || translate( substr(str, start_ + 1, instr(str, '|', start_, count_-1) - start_) , '|' , '_' ) /*Remaining string*/ || substr(str, instr(str, '|', start_, count_ - 1) + 1) ; end; --
db<>fiddle here
在您的简单示例中,更容易指定两个事件:
regexp_replace(
str
, '\|([^|]+)'
||'\|([^|]+)' -- 2 times just to make it more readable
||'(.*)' -- others
,'__'
,14
)
带有测试数据的完整示例:DBFiddle
with t as (
select
'ABC|1234|mno|p|q|r|456|XYZ|QRS|TUV' str
,'ABC|1234|mno|p_q_r|456|XYZ|QRS|TUV' chk
from dual
)
select
str,chk,
regexp_replace(
str
, '\|([^|]+)'
||'\|([^|]+)' -- 2 times just to make it more readable
||'(.*)' -- others
,'__'
,14
) as str2
from t
/
或者如果你让它更可定制并更容易指定替换数量,你可以使用简单的内联 pl/sql 函数和这样的循环:DBFiddle
with function regexp_replaces(
source_char varchar2
,pattern varchar2
,replace_char varchar2
,position int
,cnt int
) return varchar2
as
res varchar2(4000):=source_char;
begin
for i in 1..cnt loop
res:=regexp_replace(res,pattern,replace_char,position,1);
end loop;
return res;
end;
select
str,chk,
regexp_replaces(str,'\|','_',14,2) as str2
from t;