替换oracle中的多个特殊字符

Replacing multiple special characters in oracle

我有一个要求在oracle中替换列数据第一个和最后一个位置的特殊字符。

要求: 仅允许 [][.,$'*&!%^{}-?] 和字母数字字符保留在地址数据中,其余字符必须替换为 space.I以不同的概率尝试了以下方式,但它没有按预期工作。请帮我解决这个问题。

SELECT emp_address,
       REGEXP_REPLACE(
         emp_address,
         '^[^[[][.,$'\*&!%^{}-?\]]]|[^[[][.,$'\*&!%^{}-?\]]]$'
       ) AS simplified_emp_address
FROM   table_name

根据 regular expression operators and metasymbols documentation:

  • ]作为(取反)字符组的第一个字符;
  • -作为最后;和
  • 不要把.紧跟在[之后,否则它可以作为联盟元素[..]的开始匹配,如果后面有第二个.表达式.

还有:

  • 将单引号加倍(以转义它,因此它不会终止字符串文字);和
  • 在捕获组中也包含 non-special 个字符 a-zA-Z0-9 否则它们将被匹配。

这给你正则表达式:

SELECT emp_address,
       REGEXP_REPLACE(
         emp_address,
         '^[^][,.$''\*&!%^{}?a-zA-Z0-9-]|[^][,.$''\*&!%^{}?a-zA-Z0-9-]$'
       ) AS simplified_emp_address
FROM   table_name

其中,对于示例数据:

CREATE TABLE table_name (emp_address) AS
SELECT '"test1"' FROM DUAL UNION ALL
SELECT '$test2$' FROM DUAL UNION ALL
SELECT '[test3]' FROM DUAL UNION ALL
SELECT 'test4' FROM DUAL UNION ALL
SELECT '|test5|' FROM DUAL;

输出:

EMP_ADDRESS SIMPLIFIED_EMP_ADDRESS
"test1" test1
$test2$ $test2$
[test3] [test3]
test4 test4
|test5| test5

db<>fiddle here

您不需要正则表达式,因为它们会有繁琐的转义序列。使用子字符串和 translate 函数:

with a as (
  select
    'some [data ]' as val
  from dual
  union all
  select '{test $' from dual
  union all
  select 'clean $%&* value' from dual
  union all
  select 's' from dual
)
select
  translate(substr(val, 1, 1), q'{ [][.,$'*&!%^{}-?]}', ' ')
  || substr(val, 2, lengthc(val) - 2)
  || case
       when lengthc(val) > 1
       then translate(substr(val, -1), q'{ [][.,$'*&!%^{}-?]}', ' ')
     end
  as value_replaced
from a
| VALUE_REPLACED   |
| :--------------- |
| some [data       |
| test             |
| clean $%&* value |
| s                |

db<>fiddle here