有一些限制的 Initcap
Initcap with some restrictions
我想将全名的每个首字母大写,但有一个例外:介词必须小写。
介词有:["da"、"de"、"di"、"do"、"du"、"das"、"des", "dis", "dos", "dus"].
到目前为止我已经有了这段代码,但它很糟糕而且不完整。如果我这样做(放入我需要的所有例外),它将是如此之大。
DBMS_OUTPUT.PUT_LINE(
REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE
(INITCAP ('ronald DAS silva'), '(D|d)a', 'da'),
'(D|d)o', 'do'), '(D|d)e', 'de'),'(D|d)o', 'do'),'(D|d)u', 'du'));
我已经尝试在 INITCAP
函数中使用 REGEXP_REPLACE
(使用此正则表达式 -> ^(d|D)[a-zA-Z]{1,2}$
),但没有成功。
那么,有没有更简单的方法呢?
编辑:
我现在有这个:
DBMS_OUTPUT.PUT_LINE(REGEXP_REPLACE(INITCAP('ronald DAS silva'), '([d|D][[:alpha:]]{1,2})', LOWER('')));
它几乎可以正常工作,但是 LOWER
函数由于某种原因没有完成他的工作,为什么?如果我放 LOWER('A') 它会起作用。
编辑 2 - 附加测试:
每个以字母 "d" 开头的名称都将转换为小写,这不应该发生。
那么有几种情况:
- 丹尼尔
- Deivid
- 迪杰斯特拉
- 唐纳德
- 多灵
完整代码
DECLARE
TYPE t_name IS VARRAY(3) OF VARCHAR2(100);
v_names t_name := t_name(' Donald dIs siLvA',
'daniEl da sIlvA XaVIeR ',
' DeYse De Olivier dA loPeS');
BEGIN
DBMS_OUTPUT.PUT_LINE(RPAD('Name w/o format', 60, ' ') ||
'Name formatted');
DBMS_OUTPUT.PUT_LINE(RPAD('---------------------', 60, ' ') ||
'---------------------');
FOR i IN 1..v_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(v_names(i), 60, ' ') ||
f_format(v_names(i)));
END LOOP;
END;
FUNCTION f_format(p_str VARCHAR2)
RETURN VARCHAR2
AS
BEGIN
RETURN REGEXP_REPLACE(
REGEXP_REPLACE(
INITCAP(p_str),
'((D)([aeiou](s|$)?))', 'd'),
'[[:space:]]+', ' ');
END;
我想我明白了。初始化整个字符串,然后查找被 space 包围的模式(记住第 1 组)。在其中,将其分开,因此第 2 组是主要资本 'D',第 3 组是其余部分,包括可选的 's'。替换为 space、小写 'd'、记住第 3 组和另一个 space。不过,我不得不建议不要在生产中使用它,因为它对于这种名称格式来说太具体了。
SQL> declare
name varchar2(20) := 'ronald dis silva';
begin
dbms_output.put_line(
REGEXP_REPLACE(INITCAP(name), '( (D)([aeiou](s|$)?) )', ' d '));
end;
/
Ronald dis Silva
SQL>
以 'd' 开头的名字适合我:
SQL> declare
2 name varchar2(20) := 'donald dis silva';
3 begin
4 dbms_output.put_line(
5 REGEXP_REPLACE(INITCAP(name), '( (D)([aeiou](s|$)?) )', ' d '));
6 end;
7 /
Donald dis Silva
一些更复杂的名称使用 WITH 子句以便更容易插入不同名称进行测试的示例:
SQL> with tbl(name) as (
select ' Donald dIs siLvA' from dual union
select 'daniEl da sIlvA XaVIeR ' from dual union
select ' DeYse De Olivier dA loPeS' from dual
)
select REGEXP_REPLACE(INITCAP(REGEXP_REPLACE(trim(name), '\s+', ' ')), '( (D)([aeiou](s|$)?) )', ' d ') newname
from tbl;
NEWNAME
--------------------------------------------------------------------------------
Donald dis Silva
Deyse de Olivier da Lopes
Daniel da Silva Xavier
SQL>
我想将全名的每个首字母大写,但有一个例外:介词必须小写。
介词有:["da"、"de"、"di"、"do"、"du"、"das"、"des", "dis", "dos", "dus"].
到目前为止我已经有了这段代码,但它很糟糕而且不完整。如果我这样做(放入我需要的所有例外),它将是如此之大。
DBMS_OUTPUT.PUT_LINE(
REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE(REGEXP_REPLACE
(INITCAP ('ronald DAS silva'), '(D|d)a', 'da'),
'(D|d)o', 'do'), '(D|d)e', 'de'),'(D|d)o', 'do'),'(D|d)u', 'du'));
我已经尝试在 INITCAP
函数中使用 REGEXP_REPLACE
(使用此正则表达式 -> ^(d|D)[a-zA-Z]{1,2}$
),但没有成功。
那么,有没有更简单的方法呢?
编辑:
我现在有这个:
DBMS_OUTPUT.PUT_LINE(REGEXP_REPLACE(INITCAP('ronald DAS silva'), '([d|D][[:alpha:]]{1,2})', LOWER('')));
它几乎可以正常工作,但是 LOWER
函数由于某种原因没有完成他的工作,为什么?如果我放 LOWER('A') 它会起作用。
编辑 2 - 附加测试:
每个以字母 "d" 开头的名称都将转换为小写,这不应该发生。
那么有几种情况:
- 丹尼尔
- Deivid
- 迪杰斯特拉
- 唐纳德
- 多灵
完整代码
DECLARE
TYPE t_name IS VARRAY(3) OF VARCHAR2(100);
v_names t_name := t_name(' Donald dIs siLvA',
'daniEl da sIlvA XaVIeR ',
' DeYse De Olivier dA loPeS');
BEGIN
DBMS_OUTPUT.PUT_LINE(RPAD('Name w/o format', 60, ' ') ||
'Name formatted');
DBMS_OUTPUT.PUT_LINE(RPAD('---------------------', 60, ' ') ||
'---------------------');
FOR i IN 1..v_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(RPAD(v_names(i), 60, ' ') ||
f_format(v_names(i)));
END LOOP;
END;
FUNCTION f_format(p_str VARCHAR2)
RETURN VARCHAR2
AS
BEGIN
RETURN REGEXP_REPLACE(
REGEXP_REPLACE(
INITCAP(p_str),
'((D)([aeiou](s|$)?))', 'd'),
'[[:space:]]+', ' ');
END;
我想我明白了。初始化整个字符串,然后查找被 space 包围的模式(记住第 1 组)。在其中,将其分开,因此第 2 组是主要资本 'D',第 3 组是其余部分,包括可选的 's'。替换为 space、小写 'd'、记住第 3 组和另一个 space。不过,我不得不建议不要在生产中使用它,因为它对于这种名称格式来说太具体了。
SQL> declare
name varchar2(20) := 'ronald dis silva';
begin
dbms_output.put_line(
REGEXP_REPLACE(INITCAP(name), '( (D)([aeiou](s|$)?) )', ' d '));
end;
/
Ronald dis Silva
SQL>
以 'd' 开头的名字适合我:
SQL> declare
2 name varchar2(20) := 'donald dis silva';
3 begin
4 dbms_output.put_line(
5 REGEXP_REPLACE(INITCAP(name), '( (D)([aeiou](s|$)?) )', ' d '));
6 end;
7 /
Donald dis Silva
一些更复杂的名称使用 WITH 子句以便更容易插入不同名称进行测试的示例:
SQL> with tbl(name) as (
select ' Donald dIs siLvA' from dual union
select 'daniEl da sIlvA XaVIeR ' from dual union
select ' DeYse De Olivier dA loPeS' from dual
)
select REGEXP_REPLACE(INITCAP(REGEXP_REPLACE(trim(name), '\s+', ' ')), '( (D)([aeiou](s|$)?) )', ' d ') newname
from tbl;
NEWNAME
--------------------------------------------------------------------------------
Donald dis Silva
Deyse de Olivier da Lopes
Daniel da Silva Xavier
SQL>