REGEXP_REPLACE具有函数调用的反向引用

时间:2019-01-22 09:22:51

标签: sql oracle regexp-replace

我可以对REGEXP_REPLACE后向引用值使用一些函数调用吗?

例如,我想对后向引用值调用chr()或任何其他函数,但这

SELECT REGEXP_REPLACE('a 98 c 100', '(\d+)', ASCII('\1')) FROM dual;

仅返回ASCII值“ \”:

  

'a 92 c 92'

我希望最后一个参数(替换字符串)首先被求值,然后替换字符串。因此结果将是:

  

'a b c d'

2 个答案:

答案 0 :(得分:1)

使用一个正则表达式执行此操作并不聪明,但是-分步执行,类似这样的操作可能会有所帮助。它将源字符串分成几行,检查部分字符串是否为数字,如果是,则选择其中的SELECT A, B, LAG(A,1) OVER(ORDER BY B) AS NextA FROM foo; 。最后,所有内容都聚合回到单个字符串。

CHR

可以将其缩短一步(我有意将其保留为 ,这样您就可以一次执行一个查询并检查结果,以使事情更清楚):

SQL> with test (col) as
  2    (select 'a 98 c 100' from dual),
  3  inter as
  4    (select level lvl,
  5            regexp_substr(col, '[^ ]+', 1, level) c_val
  6     from test
  7     connect by level <= regexp_count(col, ' ') + 1
  8    ),
  9  inter_2 as
 10    (select lvl,
 11            case when regexp_like(c_val, '^\d+$') then chr(c_val)
 12                 else c_val
 13            end c_val_2
 14     from inter
 15    )
 16  select listagg(c_val_2, ' ') within group (order by lvl) result
 17  from inter_2;

RESULT
--------------------
a b c d

SQL>

[编辑:如果输入看起来不同怎么办?]

那有点简单。使用SQL> with test (col) as 2 (select 'a 98 c 100' from dual), 3 inter as 4 (select level lvl, 5 case when regexp_like(regexp_substr(col, '[^ ]+', 1, level), '^\d+$') 6 then chr(regexp_substr(col, '[^ ]+', 1, level)) 7 else regexp_substr(col, '[^ ]+', 1, level) 8 end c_val 9 from test 10 connect by level <= regexp_count(col, ' ') + 1 11 ) 12 select listagg(c_val, ' ') within group (order by lvl) result 13 from inter; RESULT -------------------- a b c d SQL> 提取数字:REGEXP_SUBSTR返回第一个数字,..., 1, 1返回第二个数字。纯... 1, 2然后用数字REPLACE替换数字。

CHR

答案 1 :(得分:1)

只是为了好玩,您可以使用XPath进行标记化,将数字转换为字符并进行聚合:

select *
from xmltable(
  'string-join(
    for $t in tokenize($s, " ") 
      return if ($t castable as xs:integer) then codepoints-to-string(xs:integer($t)) else $t,
    " ")'
  passing 'a 98 c 100' as "s"
);

Result Sequence                                                                 
--------------------------------------------------------------------------------
a b c d

初始字符串值作为$s传递; tokenize()使用空格作为分隔符将其拆分;对每个生成的$t进行评估,看是否是整数,然后通过codepoints-to-string将其转换为等效字符,否则将其保留;然后将所有令牌与string-join()重新组合。

如果原件上有多个空格,则它们会折叠成一个空格(就像使用Littlefoot的正则表达式一样)。