Oracle - 字符串 - 标点格式函数

时间:2017-10-18 16:22:10

标签: string oracle function plsql punctuation

我有FUNCTIONSTRING替换多个(连续)水平空间,并带有奇异的水平空间;

e.g。

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继续删除多个(连续的)水平空间。

例如;

如果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.

*注意:当在闭括号后直接出现逗号或句号时,而不是“{1}}'规则它将使用'否HORIZONTAL SPACE'规则。

我认为HORIZONTAL SPACE是解决此问题的最佳方法(我已经探索过使用纯SQL(FUNCTION)但代码开始变得非常混乱 - 主要是由于数据不一致)。此外,如果我希望将来添加其他规则(例如下划线规则),我假设REG_EXP更容易维护。但是,我一如既往地接受专业人士的建议。

非常感谢提前。

2 个答案:

答案 0 :(得分:1)

您可以使用REGEXP编写函数,而不是使用INSTRSUBSTR

注意:此功能不考虑出现在同一字符串中的多种模式。所以如果","并且"。"两者都表明它不会起作用。因此,您可以自己编写所需的所有转换代码,EXCEPTION处理等以涵盖此类方案。我已经告诉你如何做到这一点。您可能必须使用IF THENCASE块重写,因为我在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;
/

答案 1 :(得分:1)

我能想到的另一种方法是使用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;
/