EDIT1:对不起,我忘记了空间管理:这是一个解决方案:
SET serveroutput ON format wraped;
DECLARE
l_text varchar2(64) := 'Tristram Vladimir Chan';
l_mask VARCHAR2(64) := '.....XXXX..XX.....X.XX';
l_res VARCHAR2(64);
l_text_length INTEGER := length(l_text);
l_mask_length INTEGER := length(l_mask);
l_pos INTEGER := 1;
l_p INTEGER := -1;
l_x INTEGER := -1;
l_b INTEGER := instr(l_text, ' ');
l_lastb INTEGER := 0;
l_cpt INTEGER := 1;
BEGIN
-- in case text length doesn't match mask length
if l_mask_length > l_text_length then
l_mask := substr(l_mask, 1, l_text_length);
elsif l_text_length > l_mask_length then
l_mask := rpad(l_mask, l_text_length, '.');
end if;
l_mask_length := l_text_length;
-- loop for each sequence of characters in the mask
while l_pos <= l_mask_length loop
l_p := instr(l_mask, '.'); -- first '.' position
l_x := instr(l_mask, 'X'); -- first 'X' position
-- if "." or "X' has not been found
if l_p = 0 or l_x = 0 then
if l_p = 0 then -- no "." found, write 'X' until the end
l_res := rpad(l_res, l_text_length, 'X');
elsif l_x = 0 then -- no "X" found, write text until the end
l_res := l_res || substr(l_text, l_pos, l_text_length);
end if;
l_pos := l_mask_length+1;
else
if l_p = 1 then -- '.' found, write text until the next 'X'
l_res := l_res || substr(l_text, l_pos, l_x-1);
l_mask := substr(l_mask, l_x);
l_pos := l_pos + l_x-1;
elsif l_x = 1 then -- 'X' found, write 'X' until the next '.'
l_res := rpad(nvl(l_res,'X'), nvl(length(l_res),0)+l_p-1, 'X');
l_mask := substr(l_mask, l_p);
l_pos := l_pos + l_p-1;
end if;
end if;
-- if a ' ' is found in the original text, replace it in the result
if l_pos > l_b and l_b > l_lastb then
l_b := instr(l_text, ' ', 1, l_cpt);
l_res := substr(l_res, 1, l_b-1) || ' ' || substr(l_res,l_b+1,length(l_res));
l_lastb := l_b;
l_cpt := l_cpt + 1;
end if;
end loop;
dbms_output.put_line(l_res);
END;
结果 :TristXXX VlXXimir XhXX
也许可以改进它,我只是“按程序”写的。与其他解决方案相比,优势在于您可以在此处更改掩码。
EDIT2:我重新编写了代码,它非常简单......:
SET serveroutput ON format wraped;
DECLARE
l_text varchar2(64) := 'Tristram Vladimir Chan';
l_mask VARCHAR2(64) := '.....XX..XX....XXXX...';
l_res VARCHAR2(64);
l_text_length INTEGER := length(l_text);
l_mask_length INTEGER := length(l_mask);
l_pos INTEGER := 1;
BEGIN
-- in case text length doesn't match mask length
if l_mask_length > l_text_length then
l_mask := substr(l_mask, 1, l_text_length);
elsif l_text_length > l_mask_length then
l_mask := rpad(l_mask, l_text_length, '.');
end if;
l_mask_length := l_text_length;
-- loop and build the result string
while l_pos <= l_mask_length loop
if substr(l_mask, l_pos, 1) = 'X' then
l_res := l_res || 'X';
else
l_res := l_res || substr(l_text, l_pos, 1);
end if;
if substr(l_text, l_pos, 1) = ' ' then
l_res := substr(l_res, 1, l_pos-1) || ' ';
end if;
l_pos := l_pos + 1;
end loop;
dbms_output.put_line(l_res);
END;
结果 :TristXXm XXadimXX Xhan