Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String Oracle-字符串-标点符号格式化函数_String_Oracle_Function_Plsql_Punctuation - Fatal编程技术网

String Oracle-字符串-标点符号格式化函数

String Oracle-字符串-标点符号格式化函数,string,oracle,function,plsql,punctuation,String,Oracle,Function,Plsql,Punctuation,我有一个函数,它将字符串中的多个(连续)水平空格替换为单个水平空格 e、 g 功能如下: 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 || '

我有一个
函数
,它将
字符串
中的多个(连续)水平空格替换为单个水平空格

e、 g

功能如下:

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;
不过,我想进一步介绍一下这个
函数
,这样它就能够纠正基本的标点格式(逗号、句号和括号)。但是,函数继续删除多个(连续的)水平空间很重要

比如,

如果
STR\u ORIG='Hello,Marc'
输出将变成
'Hello,Marc'

如果
STR\u 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.
*注意:当右括号后面直接出现逗号或句号时,它将使用“无
水平空间
”规则,而不是“一
水平空间
”规则

我相信
函数
是解决此问题的最佳方法(我已经使用纯SQL(
REG\u EXP
)进行了探索,但代码开始变得非常混乱-主要是因为数据不一致)。此外,如果我想在将来添加其他规则(例如下划线规则),我假设
函数
更易于维护。然而,像往常一样,我愿意听取专业人士的建议


非常感谢。

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

<强>注:此函数不考虑在同一字符串中出现多种类型的模式。所以,如果“,”和“,”都出现,它将不起作用。因此,您可以自己编写所需的所有转换代码、

EXCEPTION
处理等,以涵盖此类场景。我已经给了你如何做的想法。对于类似PL/SQL的代码,您可能必须使用
IF-THEN
CASE
块重写,正如我在
with
子句中编码的那样

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;
/

与使用
INSTR
SUBSTR
相比,您可以使用
REGEXP
编写函数

<强>注:此函数不考虑在同一字符串中出现多种类型的模式。所以,如果“,”和“,”都出现,它将不起作用。因此,您可以自己编写所需的所有转换代码、

EXCEPTION
处理等,以涵盖此类场景。我已经给了你如何做的想法。对于类似PL/SQL的代码,您可能必须使用
IF-THEN
CASE
块重写,正如我在
with
子句中编码的那样

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;
/

我可以想到的另一种方法是使用
关联数组
来存储模式和替换,而不是普通的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;
/

我可以想到的另一种方法是使用
关联数组
来存储模式和替换,而不是普通的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;
/

太棒了,谢谢你,考希克·纳亚克-我很快会测试的。非常感谢。不幸的是,这可以编译,但经过测试,它会导致
ORA-01422:exact fetch返回的行数超过请求的行数。发布前测试-多好的概念啊!:-)太棒了,谢谢你,考希克·纳亚克-我很快会测试的。非常感谢。不幸的是,这可以编译,但经过测试,它会导致
ORA-01422:exact fetch返回的行数超过请求的行数。发布前测试-多好的概念啊!:-)这太棒了,@Kaushik Nayak!我真的很感谢你抽出时间来做这件事——非常感谢。这件事太棒了,@Kaushik Nayak!我真的很感谢你抽出时间来做这件事,非常感谢。