Tia*_*rge 1 regex string oracle plsql count
我有一个逗号分隔值的文件,如下所示:
1.42104E+16,220899,1,,e-page remote auto,,,"Allied Martian Banks, P.L.C.",Moon,MN,,
1.42105E+16,637039,1,,e-page remote auto,,,Bank Of Jupiter,Europa,IO,,
Run Code Online (Sandbox Code Playgroud)
我想计算一些逗号的数量,不包括引号中的那些,例如"Allied Martian Banks,PLC".
我知道:
length(i.data_record)-length(replace(i.data_record,',',''))
Run Code Online (Sandbox Code Playgroud)
将返回逗号的数量,但是这将在第一行中计算额外的逗号而不是第二行,为此我们应该将它们计为具有相同的数字.
是否有任何快速简单的方法可以忽略引号中的逗号?
我知道我可以创建一个循环并开始按位分解字符串,计算它们,每当我找到引号时忽略任何逗号,直到找到另一个引号,但是我想知道是否有更简单,更简化的方式在不诉诸循环的情况下实现这一点.
非常感谢!
首先消除分隔的内容,然后计算:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, '(^|,)"[^"]*"(,|$)'
, '\1\2'
)
, ','
)
Run Code Online (Sandbox Code Playgroud)
regexp_replace遗憾的是,为了正确处理连续的引号分隔字段,不需要嵌套调用:正则表达式模式消耗任何分隔逗号,因此后续匹配不会考虑这些逗号.
Oracle的regexen不支持前瞻操作符,这是处理这种情况的自然方式.
鉴于regexp _...调用的性能受到影响,您最好使用它
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '\1\2' ),',','' ) )
Run Code Online (Sandbox Code Playgroud)
警告
此解决方案不处理字段值中的dquotes,字段值通常表示为""或\".
可以优雅地处理前一种情况:不要""将引号分隔字段内部解释,而是将整个字段内容视为一个或多个不包含dquotes的dquote分隔字符串的并置.虽然您在处理数据时不会遵循此路线(所有dquotes都将丢失),但您可以使用此透视图进行计数:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '\1\3' -- changed
)
, ','
)
Run Code Online (Sandbox Code Playgroud)
测试用例
-- works
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"""data"",and more so",2,"more data,and even more so"', '(^|,)("[^"]*")+(,|$)', '\1\3' ), '(^|,)("[^"]*")+(,|$)', '\1\3' ), ',' ) from dual;
-- fails
select regexp_count ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
select regexp_count ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '\1\2' ), ',' ) from dual;
Run Code Online (Sandbox Code Playgroud)