是否可以使用函数进行 regexp_replace ?

发布于 2024-10-02 11:05:04 字数 729 浏览 1 评论 0原文

我想对字符串中的值进行一些计算,最后替换它们。 Oracle 正则表达式似乎很好,但 \1 在所有计算结束时都会被评估。所以我想知道我是否可以在将其传递给函数之前进行评估?

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

三生一梦 2024-10-09 11:05:04

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

但是你可以这样做,但是处理会很慢,但是它应该可以工作。我基于这个链接

集 您可以看到我只是循环

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}

放入 varchar2 表中,然后使用函数结果逐行进行替换(请注意)。可能是更有效的方法,我并不是在追求效率,而是只是为了让它发挥作用)

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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文