2017-05-05 28 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中提供的佔位符)。

相關問題