Oracle中如何用•替换单词的一半字符?求助实现方案
实现单词半隐藏的REGEXP_REPLACE解决方案
需求回顾
需要将每个单词的后半部分字符替换为•,规则明确:
- 计算单词长度,保留前半部分(长度向上取整:比如长度5保留前3位,长度8保留前4位)
- 示例:
question→ques••••,World→wor••,目标字符串Stack Overflow需输出Sta•• Over••••
可行方案
方案1:拆分单词处理后拼接(推荐)
Oracle的REGEXP_REPLACE无法直接在替换逻辑中动态计算单个单词的长度,因此先拆分字符串为独立单词,分别处理后再拼接是最清晰的方案:
SELECT LISTAGG( -- 保留前半部分 + 生成对应数量的• SUBSTR(word, 1, CEIL(LENGTH(word)/2)) || RPAD('', FLOOR(LENGTH(word)/2), '•'), ' ' ) WITHIN GROUP (ORDER BY pos) AS masked_text FROM XMLTABLE( -- 按空格拆分字符串,记录单词位置保证顺序 'for $i in tokenize(., " ") return <word pos="{position()}">{data($i)}</word>' PASSING 'Stack Overflow' -- 替换为你的目标字符串 COLUMNS pos NUMBER PATH '@pos', word VARCHAR2(200) PATH '.' );
执行后直接得到期望结果:Sta•• Over••••
方案2:纯REGEXP_REPLACE实现(技巧性写法)
如果必须仅用REGEXP_REPLACE,可以结合分组匹配和动态长度计算,写法如下:
SELECT LISTAGG( REGEXP_REPLACE( word, '^(\w{' || CEIL(LENGTH(word)/2) || '})(.*)$', '\1' || RPAD('', LENGTH(word) - CEIL(LENGTH(word)/2), '•') ), ' ' ) WITHIN GROUP (ORDER BY pos) AS masked_text FROM XMLTABLE( 'for $i in tokenize(., " ") return <word pos="{position()}">{data($i)}</word>' PASSING 'Stack Overflow' COLUMNS pos NUMBER PATH '@pos', word VARCHAR2(200) PATH '.' );
原有SQL问题分析
你之前的代码:
SELECT REGEXP_REPLACE(REGEXP_REPLACE('Stack Overflow','(\w)\w','\1*'), '\*\w', '**') FROM DUAL;
逻辑是每两个字符保留第一个,替换第二个为*,再将后续的*+字符替换为**,最终导致每个单词仅保留首字符,完全不符合“保留前半部分”的规则,因此得到S•••• O•••••••的错误结果。
内容的提问来源于stack exchange,提问作者Anne.07
相关产品推荐
相关产品推荐

