2017-05-05 81 views
0

我使用积极的后顾之道编写了一个正则表达式,但Oracle不能使用lookbehinds,所以我有点不知所措。Oracle 11g中的变量元素字符串匹配

//test string without suffix 
Last_name, First_name Middle_initial:(some_other_unimportant_stuff) 

//test string with suffix 
Last_name Suffix, First_name Middle_initial:(some_other_unimportant_stuff) 

我尝试分析一些数据出来使用下面的查询表:

SELECT 
    regexp_substr(displayname,'[^,]*') AS last_name, 
    regexp_substr(displayname,'(?<=,)[^\]]+\s') AS first_name, 
    upper(substr(regexp_substr(displayname,'[A-Za-z]:'),0,1)) AS middle_initial 
FROM table 

我能够得到last_namemiddle initial,但first_name引起了我的问题。任何关于如何重写正则表达式以获取名字的想法,或者使用oracle函数中的烘焙来完成相同的事情? TIA

+0

尝试'regexp_substr(au.displayname,',\ s *(\ w +)\ s',1,NULL,1)''。这将在有空间时以及在名字前没有空格时起作用。 –

+0

不要忘记考虑名称中可能包含特殊字符(如单引号,空格,连字符等)的事实。可以将猴子扳手放入解析算法中。确保仔细测试。首先对您的数据进行一些健全性检查,以确定您需要处理的数据类型。希望在输入端发生一些洗刷,所以你不必处理任何太疯狂的事情(是的,对)。 –

+0

@Gary_W我同意,但我已经知道这些值是什么,这是一次更大的一次导入的一部分。这些值是由客户端提供的,所以我不相信它们会从发送的原始数据中改变。任何其他用户将通过正在支持的应用程序添加。 –

回答

1

这是一个可以让维护更容易的方法,因为正则表达式是相同的。通过对它们进行分组来分解它们,然后为每个元素选择所需的组。请注意,分隔符未分组。如果first_name中有空格,它将不起作用。

SQL> with tbl(str) as (
      select 'Last_name, First_name Middle_initial:(some_other_unimportant_stuff)' from dual union 
      select 'Last_name Suffix, First_name Middle_initial:(some_other_unimportant_stuff)' from dual 
    ) 
    select regexp_substr(str, '(.*?), (.*?) (.*?):', 1, 1, NULL, 1) Last, 
      regexp_substr(str, '(.*?), (.*?) (.*?):', 1, 1, NULL, 2) First, 
      regexp_substr(str, '(.*?), (.*?) (.*?):', 1, 1, NULL, 3) Middle 
    from tbl; 

    LAST    FIRST   MIDDLE 
    ------------------ --------------- --------------- 
    Last_name Suffix First_name  Middle_initial 
    Last_name   First_name  Middle_initial 

    SQL> 

编辑:更新每个新名称的要求。我放弃了正则表达式的全部是相同的,而不是通过将它们锚定到字符串的开头来加强它们。对于姓氏,返回组,后跟逗号空格。名字是由逗号空间和空格包围的组,最后的中间名是由最后一个空格和冒号包围的字符组。问号使得该组是可选的,因此它应该处理如测试数据中所示的NULL名。像往常一样,测试意外!

SQL> with tbl(str) as (
     select 'Last_name, First_name Middle_initial:(some_other_unimportant_stuff)' from dual union 
     select 'Last_name Suffix, First_name Middle_initial:(some_other_unimportant_stuff)' from dual union 
     select 'Doe1, D John:(...)' from dual union 
     select 'Doe2, John D James:(...)' from dual union 
     select 'Doe3, Jane:(...)' from dual 
    ) 
    select regexp_substr(str, '^(.*?), ', 1, 1, NULL, 1) Last, 
      regexp_substr(str, '^.*, (.*?) ', 1, 1, NULL, 1) First, 
      regexp_substr(str, '^.* (.*?):', 1, 1, NULL, 1) Middle 
    from tbl; 

LAST    FIRST   MIDDLE 
------------------ --------------- --------------- 
Doe1    D    John 
Doe2    John D   James 
Doe3        Jane 
Last_name Suffix First_name  Middle_initial 
Last_name   First_name  Middle_initial 

SQL> 
+0

所以我测试了这一点,我注意到有些人的名字就像'Doe,D John:(...)','John'是中间名,另一个是'Doe,John D James'。 ..)'。我的正则表达式没有选择那些,但是这个。谢谢! –

+0

我注意到另一个问题。一些用户没有中间首字母缩写,比如'Doe,John:(...)'。你的正则表达式返回所有三个值的空值。任何想法? –

+0

这些听起来像数据输入错误。如果第一个名字是单个字母,而中间大于1个字母,则可以在那里进行测试,然后将其反转或拒绝。照顾你的假设!想法:在我的例子中选择另一个CTE(WITH语句),并从中选择,分析名字和中间名首字母,如果第一个字母是中间字母且中间字母大于一个字母,则反转。 NULL中间不在原始规格中。 : - /让我试试... –

0

这是我想出了:

//the regex for First_name 
\s[A-Za-z]+ 

这让我

, First_name 

查询现在看起来像:

SELECT 
    regexp_substr(displayname,'[^,]*') AS last_name, 
    trim(substr(regexp_substr(au.displayname,',\s[A-Za-z]+'),2)) AS first_name, 
    upper(substr(regexp_substr(displayname,'[A-Za-z]:'),0,1)) AS middle_initial 
FROM table 
1

甲骨文正则表达式不支持lookarounds。但是,您可能诉诸捕获组和访问它们的值:

regexp_substr(au.displayname, ',\s*([A-Za-z]+)\s', 1, 1, NULL, 1) AS first_name 

这里,捕获组定义与(....)最后1告诉regexp_substr只输出此子值。

这里是how this regex works(我添加了_以匹配OP中提供的占位符)。

相关问题