我想对字符串中的值进行一些计算,最后替换它们。 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.
答案 0 :(得分:2)
看起来将后向引用传递给reg ex函数中的函数是不行的(至少在我的测试中并且没有找到任何正常工作的东西(尽管有link但是很难称之为参考)
但是你可以做到这一点,但它的处理速度会缓慢但应该有效。我根据这个link
建立了这个样本在
上设置serveroutputdeclare
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表中,然后使用函数结果从那里逐行替换。 (请注意,可能有更有效的方法,我不是在追求效率,而只是为了让它发挥作用)