oracle regexp_replace的更简单的正则表达式

我有一个 | 分隔的字符串,其中包含20个 | s ,例如123|1|42|13||94123|2983191|2|98863|...|211|,最多20 |。这是一个oracle db列。字符串只有20个数字,后跟|。

我试图从中取出一个字符串,以删除位置4,6,8,9,11,12和13处的数字。此外,需要将位置16的数字移至位置4。 ,我有一个正则表达式,例如

select regexp_replace(col1,'^((\d*\|){4})(\d*\|)(\d*\|)(\d*\|)(\d*\|)((\d*\|){2})(\d*\|)((\d*\|){3})((\d*\|){2})(\d*\|)(.*)$','\1|\4|\6||\9||||||||') as cc from table

这是我遇到的麻烦,因为oracle仅支持最多9个组的反向引用。有什么方法可以使此正则表达式更简单,使其组数更少,并且可以替换?也欢迎任何其他解决方案/建议。

注意-位置计数器从0开始,因此上面字符串中的123是第0个数字。

编辑:示例-

源字符串

  

||| 14444 | 10107 | 227931 | 10115 || 10118 || 11361 | 11485 || 10110 || 11512 | 16666 |||

预期结果

  

||| 16666 | 10107 || 10115 |||||| 11512 ||||

wyb001 回答:oracle regexp_replace的更简单的正则表达式

由于有一个独特的列(如您所说,ID),请查看是否有帮助:

  • 将每一列拆分为行
  • 使用2个listagg将它们重新组成(使用CASE):
    • 一个删除不需要的值
    • 另一个对它们进行正确排序的方法(“将位置16的值放到位置4”)

请注意,我的结果与您的结果有所不同;如果我计算正确,则16666不在位置16处,而是在17处,因此-11512必须移至位置4。

我还添加了另一条 dummy 行,用于确认我是否正确计算了位置,并说明了为什么必须使用#10-12行(由于重复)。

好的,您在这里:

SQL> with test (id,col) as
  2    (
  3    select 1,'|||14444|10107|227931|10115||10118||11361|11485||10110||11512|16666|||' from dual union all
  4    select 2,'1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20'                     from dual
  5    ),6  temp as
  7    (select replace(regexp_substr(col,'(.*?)(\||$)',1,column_value),'|','') val,8            column_value lvl,9            id
 10     from test cross join table(cast(multiset(select level from dual
 11                                              connect by level <= regexp_count(col,'\|') + 1
 12                                             ) as sys.odcinumberlist))
 13    )
 14  select id,15    listagg(case when lvl in (4,6,8,9,11,12,13) then '|'
 16                 else val || case when lvl = 20 then '' else '|' end
 17            end,'')
 18            within group (order by case when lvl = 16 then 4
 19                                        when lvl =  4 then 16
 20                                        else lvl
 21                                   end) result
 22  from temp
 23  group by id;

        ID RESULT
---------- ------------------------------------------------------------
         1 |||11512|10107||10115|||||||10110|||16666|||
         2 1|2|3|16|5||7|||10||||14|15||17|18|19|20

SQL>
,

通过从字符串中删除要删除的数字的捕获组,然后将((\d*\|){2})写为(\d*\|\d*\|),可以获得所需的结果。这样可以将捕获组的数量减少到7个,从而使您的代码按原样工作:

select regexp_replace(col1,'^(\d*\|\d*\|\d*\|\d*\|)\d*\|(\d*\|)\d*\|(\d*\|)\d*\|\d*\|(\d*\|)\d*\|\d*\|\d*\|(\d*\|\d*\|)(\d*\|)(.*)$','\1\6\2|\3||\4|||\5|\7') as cc 
from table

输出(用于您的测试数据以及@Littlefoot好列示例):

CC
|||14444|16666|227931|||||11361|||||11512|||||
0|1|2|3|16|5||7|||10||||14|15||17|18|19|

Demo on dbfiddle

本文链接:https://www.f2er.com/3168503.html

大家都在问