Можно ли regexp_replace с помощью функции? - PullRequest
2 голосов
/ 15 ноября 2010

Я хотел бы сделать некоторые вычисления для значения в строке и, наконец, заменить их.Oracles regexp кажется хорошим, но \ 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.

1 Ответ

2 голосов
/ 15 ноября 2010

похоже, что передача обратной ссылки в функцию внутри функции reg ex не сработает (по крайней мере, в моем тесте и из-за отсутствия поиска чего-либо там, что работает должным образом (хотя была эта ссылка * 1002)* но это трудно назвать ссылкой)

Но вы можете сделать это, но это будет медленная за медленной обработкой, но она должна работать. Я основал этот пример из этой ссылки

установить выход сервера на

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, а затем построчно выполните замену на результаты функции (обратите внимание, что, возможно, есть более эффективные способы сделать это, я не стремился к эффективности, а скорее просто чтобы получить егоработа)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...