是否可以使用函数regexp_replace?

时间:2010-11-15 11:32:02

标签: oracle plsql

我想对字符串中的值进行一些计算,最后替换它们。 Oracles regexp看起来很好,但是在所有计算结束时都会对它进行评估。所以我想知道在将评估传递给函数之前是否可以进行评估?

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;

为您提供如下结果:

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

1 个答案:

答案 0 :(得分:2)

看起来将后向引用传递给reg ex函数中的函数是不行的(至少在我的测试中并且没有找到任何正常工作的东西(尽管有link但是很难称之为参考)

但是你可以做到这一点,但它的处理速度会缓慢但应该有效。我根据这个link

建立了这个样本

上设置serveroutput
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;

导致

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}

这是在11gR1中完成的。您可以看到我只是循环遍历这个并将结果放入varchar2表中,然后使用函数结果从那里逐行替换。 (请注意,可能有更有效的方法,我不是在追求效率,而只是为了让它发挥作用)