2

I would like to do some calculations on a value in a string and finally replace them. Oracles regexp seemes to be good but the \1 gets evaluated at the end of all calcualtions. So I am wondering if I could fore the evaluation before passing it to the function?

set serveroutput on

declare
  l_foo varchar2(4000);

  function f_test(i_t varchar2) return varchar2
  is
  begin
    dbms_output.put_line('given parameter: ' || i_t);
    return upper(i_t);
  end;
begin
  l_foo := regexp_replace(
    'http://www.scoach.com/${asset_type}/${ISIN}?eventtarget=${target}ANDeventvalue=${target_value}'
   ,'\$\{([[:alpha:]_]+)\}'
   ,f_test('\1')
  );

  dbms_output.put_line(l_foo);
end;

Gives you a result like:

given parameter: \1
http://www.scoach.com/asset_type/ISIN?eventtarget=targetANDeventvalue=target_value
PL/SQL procedure successfully completed.

1 Answer 1

2

it looks like passing the backreference into a function within the reg ex function is not going to work (at least in my test and the lack of finding anything out there that works properly (although there was this link but it is hard to call this a reference)

But you can do this, but it'll be slow-by-slow processing but it ought to work. I based this sample from this link

set serveroutput on

declare
  l_foo varchar2(4000);

  searchString varchar2(4000) ;
  searchPattern varchar2(4000) ;

  /*type matchItem is object(
       position number ,
         matchedPattern varchar2(4000));*/
  type matched is table of varchar2(100);


  l_foo2 matched;

  function f_test(i_t varchar2) return varchar2
  is
  begin
    dbms_output.put_line('given parameter: ' || i_t);
    return upper(i_t);
  end f_test;

function getNMatch(
      str    in varchar2, 
     pat    in varchar2,
      occr   in number , 
     flags in varchar2 := null
) return varchar2 is
    pos_match_begin  number;
    pos_match_end    number;
     str_used         varchar2(4000);
begin

         pos_match_begin := regexp_instr (
            str,   -- 
            pat, 
            1,     -- start position
            occr,     -- occurance
            0,     -- return option
            flags
         );

         pos_match_end   := regexp_instr (
            str,   -- 
            pat, 
            1,     -- start position
            occr,     -- occurance
            1,     -- return option
            flags
         );
         if (pos_match_begin >= 0 and pos_match_end > 0) THEN 
            str_used := substr(str, pos_match_begin, pos_match_end - pos_match_begin);
         ELSE
           str_used := null;
         end if;
         return str_used ; 

end getNMatch;

 function match (
     str    in varchar2, 
     pat    in varchar2, 
     flags in varchar2 := null) return matched is 

    ret matched;

    i number ;
     regCount number ;

      begin
        regCount :=  regexp_count(str, pat) ;
      ret := matched();

       for i in 1 .. regCount LOOP
             ret.extend() ;
              ret(i) := getNMatch(str, pat , i, flags); 
       END LOOP;

         return ret;
     end match;

 function reMatch (
     str    in varchar2, 
     pat    in varchar2, 
     flags in varchar2 := null) return varchar2
      is
      ret matched;
      str_out varchar2(4000);
      begin
      str_out := str;
        ret := match(str,pat,flags);

         for i in REVERSE 1..ret.count loop
             str_out  := regexp_replace(str_out, pat, f_test(ret(i)),1, i);
         end loop;
         return str_out ;--ret;      
      end reMatch;

begin
   searchString := 'http://www.scoach.com/${asset_type}/${ISIN}?eventtarget=${target}ANDeventvalue=${target_value}';
   searchPattern:= '\$\{([[:alpha:]_]+)\}';

    l_foo := reMatch( searchString,
     searchPattern);
    --this example will call a custom function that will auto-change the entire string as defined by you
    dbms_output.put_line(l_foo);

   --here is another example that will 'allow' you to use the count of the table's position as a pseudo backreference to pull out your items and scrub them as desired
   l_foo2 :=  match(searchString ,searchPattern);
  dbms_output.put_line('\4/\3,\2: \1 || ' || f_test(l_foo2(4)) || '/' || l_foo2(3) || ',' || l_foo2(2) || ': ' || l_foo2(1));
end;

which results in

given parameter: ${target_value}
given parameter: ${target}
given parameter: ${ISIN}
given parameter: ${asset_type}
http://www.scoach.com/${ASSET_TYPE}/${ISIN}?eventtarget=${TARGET}ANDeventvalue=${TARGET_VALUE}
given parameter: ${target_value}
\4/\3,\2: \1 || ${TARGET_VALUE}/${target},${ISIN}: ${asset_type}

This was done in 11gR1. You can see that I am just looping through this and placing the results into a varchar2 table and then doing the replacement line-by-line from there with the function results. (please note there are probably more efficient ways of doing this, I was not striving for efficiency but rather just to get it to work)

Sign up to request clarification or add additional context in comments.

1 Comment

@christian terrific, hope this works for you, if it does don't forget to mark it as the correct answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.