我一直在尝试在sqlloader中使用regex_replace将字符串中的部分解析为两个字段,ID_CLEAN_I和UNIT_I使用正则表达式
^([A-Za-z]{2,4})([\s]*|[0]*| *)([1-9][0-9]{0,5})([\s]*| *)([A-Za-z])[\s]*$
将数据解析为正则表达式组,如下所示:
Example string: ABCD123456A
Group 1) ABCD
Group 3) 123456
Group 5) A
像这样(你可以想到:在这个例子中ID_I为ABCD123456A):
ID_CLEAN_I EXPRESSION "REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})([\\s]*|[0]*| *)([1-9][0-9]{0,5})([\\s]*| *)([A-Za-z])[\\s]*$', '\\1 \\3')",
UNIT_I EXPRESSION "REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})([\\s]*|[0]*| *)([1-9][0-9]{0,5})([\\s]*| *)([A-Za-z])[\\s]*$', '\\5')"
...并且SQL-Loader永远不会得到任何匹配,但是如果我们在Oracle中使用ABCD123456A的测试字符串测试它,如:
SELECT REGEXP_REPLACE('ABCD123456A', '^([A-Za-z]{2,4})([\\s]*|[0]*| *)([1-9][0-9]{0,5})([\\s]*| *)([A-Za-z])[\s]*$', '\5')
FROM dual;
然后我们可以成功获得我们想要的任何匹配组(主要是第1,3和5组)。
所以,我的问题是针对你的SQL Loader / Oracle / Regex大师 - SQL Reader中使用的Oracle Regex和Regex之间有区别吗?如果是这样,我将如何更改我的Regex以使其更适合装载机?
编辑,根据要求,具体如下:
OPTIONS (SKIP=0,ERRORS=50,readsize=20971644,bindsize=20971520,ROWS=5000)
LOAD DATA
INFILE 'C:\Temp\text.txt'
BADFILE 'C:\Temp\text.BAD'
DISCARDFILE 'C:\Temp\text.DSC'
APPEND
PRESERVE BLANKS
INTO MyTable
WHEN (some stuff happens)
FIELDS TERMINATED BY '|' TRAILING NULLCOLS
(
ID_I, -- this could be 'ABCD123456A' or 'ABCD 123456 A' or 'ABCD000123456A'
ID_CLEAN_I EXPRESSION "REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})([\\s]*|[0]*| *)([1-9][0-9]{0,5})([\\s]*| *)([A-Za-z])[\\s]*$', '\\1 \\3')", -- we want 'ABCD 123456'
UNIT_I EXPRESSION "REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})([\\s]*|[0]*| *)([1-9][0-9]{0,5})([\\s]*| *)([A-Za-z])[\\s]*$', '\\5')" -- we want 'A'
)
/*errors - note that UNIT_I can only be a single character A, B, C, D...
Record 1: Rejected - Error on table MyTable, column UNIT_I.
ORA-12899: value too large for column "MyTable"."UNIT_I" (actual: 11, maximum: 1)
*/
答案 0 :(得分:0)
您正在使用方括号匹配字符列表表达式错误。 [\s]
将匹配文字\
或文字s
字符,而不是任何空格字符。如上所述in the documentation:
匹配括号内列表中的任何单个字符。在列表中,除这些之外的所有运算符都被视为文字:
范围运算符: -
POSIX字符类:[::] POSIX校对元素:[。 ]
POSIX字符等价类:[= =]
要使用括号查找空格,您需要使用字符类[[:space:]]
。但是你不需要在这里使用字符列表,如果第一次检查(即第二组)是空格后跟零;您可以使用the \s
operator,使您的模式更像:
'^([A-Za-z]{2,4})(\s*0*)([1-9][0-9]{0,5})(\s*)([A-Za-z])\s*$'
作为具有弥补价值的演示:
var id_i varchar2(20);
exec :id_i := 'ABC 012345 A ';
select REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})(\s*0*)([1-9][0-9]{0,5})(\s*)([A-Za-z])\s*$', '\1 \3') as id_clean_i,
REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})(\s*0*)([1-9][0-9]{0,5})(\s*)([A-Za-z])\s*$', '\5') as unit_i
from dual;
ID_CLEAN_I UNIT_I
-------------------- --------------------
ABC 12345 A
所以你的控制文件会有:
ID_I,
ID_CLEAN_I EXPRESSION "REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})(\\s*0*)([1-9][0-9]{0,5})(\\s*)([A-Za-z])\\s*$', '\\1 \\3')",
UNIT_I EXPRESSION "REGEXP_REPLACE(:ID_I, '^([A-Za-z]{2,4})(\\s*0*)([1-9][0-9]{0,5})(\\s*)([A-Za-z])\\s*$', '\\5')"
您添加到问题的三个示例值全部加载,ID_CLEAN_I
设置为'ABCD 123456'
,UNIT_I
设置为'A'
。