注意:此问题最初是在c ++ regexp_replace
的上下文中提出的(请参阅here)。然而,我想到它也可能对甲骨文宇宙感兴趣。该问题的措辞已获得原作者的许可。
Perl具有e
正则表达式修饰符,它允许使用Perl代码而不仅仅是字符串来表示替换:http://perldoc.perl.org/perlretut.html#Search-and-replace尽管该示例并不是最好的,因为有切换来实现此目的。对于那些了解Perl的人来说,这是一个更有意义的例子:
$string = "StackOverflow user: Old Faithful";
$string =~ s/:\s*(.*)$/$1 == "Old Faithful" ? ": ".$1." is AWESOME!" : ": ".$1." is ???"/e;
print $string; #Will print "StackOverflow user: Old Faithful is AWESOME!"
(Pl)Sql中是否有regex_replace
变体允许我做类似的事情?如代码内联替换。
答案 0 :(得分:2)
不幸的是,REGEX_REPLACE
不适合动态生成的替换字符串。
但是,你可以近距离接触。这个答案包含3个相同想法的变体。简而言之:
变化1:静态
最简单的,仅在表达式语法中计算,sql兼容,性能噩梦
变体2:静态+函数调用
简单,复杂的计算,sql兼容,性能噩梦;
创建所需功能/包的权限。
变化3:动态
复杂,执行代码的最大灵活性,而不是sql兼容,性能......你猜对了。
所有方法的基本思想是使用REGEXP_SUBSTR
来获取捕获组内容,并将这些内容提供给计算实际替换它的数据的代码。
在变体1中,此代码将是表达式本身,变体2将此代码隐藏在函数体中,变体3将其实现为围绕它的动态plsql块。
变式1(静态)
使用REGEXP_SUBSTR
获取捕获组内容并提供表达式以相应地处理此数据:
set serveroutput on
DECLARE
text_orig_yep VARCHAR2(1000) := 'StackOverflow user: Old Faithful';
text_orig_nay VARCHAR2(1000) := 'StackOverflow user: Some Nobody';
text_pattern VARCHAR2(1000) := ':\s*(.*)$';
text_repl VARCHAR2(1000);
BEGIN
text_repl :=
REGEXP_REPLACE (
text_orig_yep
, text_pattern
, CASE REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)
WHEN 'Old Faithful' THEN REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is AWESOME!'
ELSE REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is ???'
END
);
dbms_output.put_line ( text_repl );
text_repl :=
REGEXP_REPLACE (
text_orig_nay
, text_pattern
, CASE REGEXP_SUBSTR(text_orig_nay, text_pattern, 1, 1, '', 1)
WHEN 'Old Faithful' THEN REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is AWESOME!'
ELSE REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)||' is ???'
END
);
dbms_output.put_line ( text_repl );
END;
/
show error
变体2(静态+函数调用)
使用REGEXP_SUBSTR
获取捕获组内容并提供一个函数来计算结果。这样,您就可以执行复杂的计算,这些计算不可能或很麻烦,无法表达为plsql表达式。
set serveroutput on
CREATE OR REPLACE FUNCTION test_rreval ( match_1 IN VARCHAR2 ) RETURN VARCHAR2
IS
BEGIN
RETURN
CASE match_1
WHEN 'Old Faithful' THEN match_1||' is AWESOME!'
ELSE match_1||' is ???'
END
;
END test_rreval;
/
show error
DECLARE
text_orig_yep VARCHAR2(1000) := 'StackOverflow user: Old Faithful';
text_orig_nay VARCHAR2(1000) := 'StackOverflow user: Some Nobody';
text_pattern VARCHAR2(1000) := ':\s*(.*)$';
text_repl VARCHAR2(1000);
BEGIN
text_repl :=
REGEXP_REPLACE (
text_orig_yep
, text_pattern
, test_rreval ( REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1) )
);
dbms_output.put_line ( text_repl );
text_repl :=
REGEXP_REPLACE (
text_orig_nay
, text_pattern
, test_rreval ( REGEXP_SUBSTR(text_orig_nay, text_pattern, 1, 1, '', 1) )
);
dbms_output.put_line ( text_repl );
END;
/
show error
变式3(动态)
通过生成动态plsql块来生成结果,您可以以性能和可维护性为代价获得最大的灵活性。作为一种优势,您可以更接近perl语法(但您可以相应地调整变体2)。
set serveroutput on
DECLARE
text_orig_yep VARCHAR2(1000) := 'StackOverflow user: Old Faithful';
text_orig_nay VARCHAR2(1000) := 'StackOverflow user: Some Nobody';
text_pattern VARCHAR2(1000) := ':\s*(.*)$';
text_repl VARCHAR2(1000);
dyncode VARCHAR2(32000);
BEGIN
dyncode := 'DECLARE "$1" VARCHAR2(32000) := :1; BEGIN :outvar := REGEXP_REPLACE ( :text_orig, :text_pattern, CASE "$1" WHEN ''Old Faithful'' THEN "$1"||'' is AWESOME!'' ELSE "$1"||'' is ???'' END ); END;';
EXECUTE IMMEDIATE dyncode
USING IN REGEXP_SUBSTR(text_orig_yep, text_pattern, 1, 1, '', 1)
, OUT text_repl
, IN text_orig_yep
, IN text_pattern
;
dbms_output.put_line ( text_repl );
EXECUTE IMMEDIATE dyncode
USING IN REGEXP_SUBSTR(text_orig_nay, text_pattern, 1, 1, '', 1)
, OUT text_repl
, IN text_orig_nay
, IN text_pattern
;
dbms_output.put_line ( text_repl );
END;
/
show error