Oracle - 字符串 - 标点符号格式化函数
Oracle - String - Punctuation Formatting Function
我有一个 FUNCTION
将 STRING
中的多个(连续)水平 Space 替换为单个水平 Space;
例如
STR_ORIG = 'Hello World'
STR_NEW = 'Hello World'
函数如下;
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
INS VARCHAR2)
RETURN VARCHAR2
AS
OUTSTR VARCHAR2(4000);
STR VARCHAR2(4000);
BEGIN
STR := INS;
WHILE (INSTR(STR,' ',1) > 0 )
LOOP
OUTSTR := OUTSTR || ' ' || SUBSTR(STR,1,INSTR(STR,' ',1) - 1);
STR := TRIM(BOTH ' ' FROM SUBSTR(STR,INSTR(STR,' ',1)));
END LOOP;
OUTSTR := OUTSTR || ' ' || TRIM(STR);
RETURN TRIM(OUTSTR);
END CP_RDN_PUNCT;
不过,我想对此进行扩展 FUNCTION
以便它能够更正基本的标点符号格式(逗号、句点和括号)。但是,重要的是 FUNCTION 继续删除多个(连续的)水平 Spaces.
例如;
如果 STR_ORIG = 'Hello , Marc'
输出将变为 'Hello, Marc'
如果 STR_ORIG = 'Hello.Marc'
输出将变为 'Hello. Marc'
如果 STR_ORIG = 'Hello(Marc )'
输出将变为 'Hello (Marc)'
我想使用的规则非常基本:
Comma;...............One HORIZONTAL SPACE after a Comma.
No HORIZONTAL SPACE before a Comma.
Full Stop;...........One HORIZONTAL SPACE after a Full Stop.
No HORIZONTAL SPACE before a Full Stop.
Open Parenthesis;....No HORIZONTAL SPACE after an Open Parenthesis.
One HORIZONTAL SPACE before an Open Parenthesis.
Closed Parenthesis;..One HORIZONTAL SPACE after an Closed Parenthesis*.
No HORIZONTAL SPACE before an Closed Parenthesis.
*注意:当逗号或句号直接出现在右括号之后时,它将使用 'No HORIZONTAL SPACE
' 规则而不是 'One HORIZONTAL SPACE
' 规则。
我相信 FUNCTION
是解决这个问题的最佳方法(我已经探索过使用纯 SQL (REG_EXP
) 但代码开始变得相当混乱 - 主要是由于不一致在数据中)。另外,如果我想在将来添加额外的规则(例如下划线规则),我假设 FUNCTION
会更容易维护。但是,一如既往,我愿意听取专业人士的建议。
非常感谢。
您可以使用 REGEXP
编写函数,而不是使用 INSTR
、SUBSTR
。
注意:此函数不考虑同一字符串中出现的多种模式。因此,如果“,”和“。”都出现,它将不起作用。因此,您可以自己编写所有需要的转换代码,EXCEPTION
处理等来涵盖此类场景。我已经给了你关于如何完成的想法。您可能需要用 IF THEN
或 CASE
块重写,因为我在 with
子句中编码了类似 PL/SQL 的代码。
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
inp_pattern VARCHAR2)
RETURN VARCHAR2
AS
outstr VARCHAR2(4000);
BEGIN
with reg ( pattern, regex ,replacement ) AS
(
select ',' , ' *, *', ', ' FROM DUAL UNION ALL
select '.' , ' *\. *', '. ' FROM DUAL UNION ALL
select '(' , ' *\( *', ' (' FROM DUAL
)
SELECT
TRIM(regexp_replace(rep,' *\) *',') ') ) INTO outstr
FROM
(
SELECT
regexp_replace(inp_pattern,regex,replacement) rep
FROM
reg
WHERE
inp_pattern LIKE '%'
|| pattern
|| '%'
);
RETURN outstr;
END;
/
我能想到的另一种方法是使用 associated array
来存储模式和替换而不是普通的 sql。然后在循环中对字符串应用每个转换。
CREATE OR REPLACE FUNCTION cp_rdn_punct2 (
inp_pattern VARCHAR2
) RETURN VARCHAR2 AS
v_outstr VARCHAR2(1000) := inp_pattern;
TYPE v_astype IS
TABLE OF VARCHAR2(40) INDEX BY VARCHAR(40);
v_pat v_astype;
v_idx VARCHAR2(40);
BEGIN
v_pat(' *, *' ) := ', ';
v_pat(' *\. *') := '. ';
v_pat(' *\( *') := ' (';
v_pat(' *\) *') := ') ';
v_idx := v_pat.first;
WHILE v_idx IS NOT NULL LOOP
v_outstr := regexp_replace(v_outstr,v_idx,v_pat(v_idx) );
v_idx := v_pat.next(v_idx);
END LOOP;
RETURN v_outstr;
END;
/
我有一个 FUNCTION
将 STRING
中的多个(连续)水平 Space 替换为单个水平 Space;
例如
STR_ORIG = 'Hello World'
STR_NEW = 'Hello World'
函数如下;
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
INS VARCHAR2)
RETURN VARCHAR2
AS
OUTSTR VARCHAR2(4000);
STR VARCHAR2(4000);
BEGIN
STR := INS;
WHILE (INSTR(STR,' ',1) > 0 )
LOOP
OUTSTR := OUTSTR || ' ' || SUBSTR(STR,1,INSTR(STR,' ',1) - 1);
STR := TRIM(BOTH ' ' FROM SUBSTR(STR,INSTR(STR,' ',1)));
END LOOP;
OUTSTR := OUTSTR || ' ' || TRIM(STR);
RETURN TRIM(OUTSTR);
END CP_RDN_PUNCT;
不过,我想对此进行扩展 FUNCTION
以便它能够更正基本的标点符号格式(逗号、句点和括号)。但是,重要的是 FUNCTION 继续删除多个(连续的)水平 Spaces.
例如;
如果 STR_ORIG = 'Hello , Marc'
输出将变为 'Hello, Marc'
如果 STR_ORIG = 'Hello.Marc'
输出将变为 'Hello. Marc'
如果 STR_ORIG = 'Hello(Marc )'
输出将变为 'Hello (Marc)'
我想使用的规则非常基本:
Comma;...............One HORIZONTAL SPACE after a Comma.
No HORIZONTAL SPACE before a Comma.
Full Stop;...........One HORIZONTAL SPACE after a Full Stop.
No HORIZONTAL SPACE before a Full Stop.
Open Parenthesis;....No HORIZONTAL SPACE after an Open Parenthesis.
One HORIZONTAL SPACE before an Open Parenthesis.
Closed Parenthesis;..One HORIZONTAL SPACE after an Closed Parenthesis*.
No HORIZONTAL SPACE before an Closed Parenthesis.
*注意:当逗号或句号直接出现在右括号之后时,它将使用 'No HORIZONTAL SPACE
' 规则而不是 'One HORIZONTAL SPACE
' 规则。
我相信 FUNCTION
是解决这个问题的最佳方法(我已经探索过使用纯 SQL (REG_EXP
) 但代码开始变得相当混乱 - 主要是由于不一致在数据中)。另外,如果我想在将来添加额外的规则(例如下划线规则),我假设 FUNCTION
会更容易维护。但是,一如既往,我愿意听取专业人士的建议。
非常感谢。
您可以使用 REGEXP
编写函数,而不是使用 INSTR
、SUBSTR
。
注意:此函数不考虑同一字符串中出现的多种模式。因此,如果“,”和“。”都出现,它将不起作用。因此,您可以自己编写所有需要的转换代码,EXCEPTION
处理等来涵盖此类场景。我已经给了你关于如何完成的想法。您可能需要用 IF THEN
或 CASE
块重写,因为我在 with
子句中编码了类似 PL/SQL 的代码。
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
inp_pattern VARCHAR2)
RETURN VARCHAR2
AS
outstr VARCHAR2(4000);
BEGIN
with reg ( pattern, regex ,replacement ) AS
(
select ',' , ' *, *', ', ' FROM DUAL UNION ALL
select '.' , ' *\. *', '. ' FROM DUAL UNION ALL
select '(' , ' *\( *', ' (' FROM DUAL
)
SELECT
TRIM(regexp_replace(rep,' *\) *',') ') ) INTO outstr
FROM
(
SELECT
regexp_replace(inp_pattern,regex,replacement) rep
FROM
reg
WHERE
inp_pattern LIKE '%'
|| pattern
|| '%'
);
RETURN outstr;
END;
/
我能想到的另一种方法是使用 associated array
来存储模式和替换而不是普通的 sql。然后在循环中对字符串应用每个转换。
CREATE OR REPLACE FUNCTION cp_rdn_punct2 (
inp_pattern VARCHAR2
) RETURN VARCHAR2 AS
v_outstr VARCHAR2(1000) := inp_pattern;
TYPE v_astype IS
TABLE OF VARCHAR2(40) INDEX BY VARCHAR(40);
v_pat v_astype;
v_idx VARCHAR2(40);
BEGIN
v_pat(' *, *' ) := ', ';
v_pat(' *\. *') := '. ';
v_pat(' *\( *') := ' (';
v_pat(' *\) *') := ') ';
v_idx := v_pat.first;
WHILE v_idx IS NOT NULL LOOP
v_outstr := regexp_replace(v_outstr,v_idx,v_pat(v_idx) );
v_idx := v_pat.next(v_idx);
END LOOP;
RETURN v_outstr;
END;
/