LPAD and REGEXP_REPLACE interaction gone wonky?

Dit*_*tto 2 regex oracle

got something here I can't explain, hoping to get some help seeing what I'm obviously missing :)

While working on a solution for this question: Oracle SQL to Sort Version Numbers

I figured a clever regexp_replace + LPAD would results in a nicer sorted value. However, for some reason the LPAD kept misbehaving. Here's the "issue" in a simplified test:

  with w_data as (
     select '9'  v  from dual union all
     select '18' v  from dual
     )
  select v,
         lpad(v, 4, '0' ) a,
         regexp_replace(v, '([0-9]*)', lpad('\1', 4, '0')) b
  from w_data
  /

  V  
  -- 
  A
  ----
  B
  ----------
  9  
  0009
  00900

  18 
  0018
  001800


  2 rows selected.
Run Code Online (Sandbox Code Playgroud)

so as you can see, column "a" behaves as expected .. a length 4 string, with 0's padded on left ..

However, once it goes through the regexp_replace ... it starts to get weird ... why does it behave like that ? How do I use it in conjunction with regexp_replace "properly" ? (note that my regular expression and string - as per the linked question - is a bit more complex ;) )

[edit] tried with "[0-9]+" .. still not padding properly though ..

  with w_data as (
     select '9'  v  from dual union all
     select '18' v  from dual
     )
  select v,
         lpad(v, 4, '0' ) a,
         regexp_replace(v, '([0-9]+)', lpad('\1', 4, '0')) b
  from w_data
  /

  V  
  -- 
  A
  ----
  B
  ----------
  9  
  0009
  009

  18 
  0018
  0018


  2 rows selected.
Run Code Online (Sandbox Code Playgroud)

Note that the 18 comes out correctly ("0018") , however, the 9 comes out as "009" only 3 characters? should be four: "0009" ...

小智 5

如果您确定所有数字不超过 4 位,您可以使用以下命令:

with w_data as (
   select '9'  v  from dual union all
   select '18' v  from dual
   )
select v,
       REGEXP_REPLACE(
         REGEXP_REPLACE(v, '([0-9]+)', '000\1'),
         '(0*)([0-9]{4})', 
         '\2') b
from w_data
Run Code Online (Sandbox Code Playgroud)

如果没有,这里有更复杂的解决方案:

with w_data as (
   select '9'  v  from dual union all
   select '18'  v  from dual union all
   select '123456' v  from dual
   )
select v,
       REGEXP_REPLACE(
         REGEXP_REPLACE(v, '([0-9]+)', '000\1'),
         '(0*)([1-9]?[0-9]{4})', 
         '\2') b
from w_data
Run Code Online (Sandbox Code Playgroud)