如何计算字符串中分隔符的出现次数,不包括引号中的分隔符
How to count occurrences of separator in string excluding those in quotes
我有一个包含逗号分隔值的文件,如下所示:
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,,
我想统计除引号外的逗号的个数,例如"Allied Martian Banks, P.L.C.".
我知道:
length(i.data_record)-length(replace(i.data_record,',',''))
会 return 逗号的数量,但是与第二行相比,这会在第一行中计算一个额外的逗号,对于我来说,它们应该被算作具有相同的数字。
有什么快速简单的方法可以忽略引号中的逗号吗?
我知道我可以创建一个循环并开始按位分解字符串,计算它们,每当我找到引号时忽略任何逗号,直到找到另一个引号,但是我想知道是否有更简单的方法,无需借助循环即可实现此目的的更简化方法。
非常感谢!
先去掉分隔的内容,再数:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, ''
)
, '(^|,)"[^"]*"(,|$)'
, ''
)
, ','
)
不幸的是,为了正确处理连续的引号分隔字段,需要嵌套 regexp_replace
调用:正则表达式模式会消耗任何分隔逗号,因此不会在后续匹配中考虑。
Oracle 的 regexen 不支持先行运算符,这将是处理这种情况的自然方式。
考虑到 regexp_... 调用的性能影响,您最好使用
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '' ),',','' ) )
警告
此解决方案不处理字段值中的双引号,通常表示为 ""
或 \"
。
前一种情况可以优雅地处理:与其解释引号分隔字段内的 ""
,不如将整个字段内容视为 1 个或多个不包含双引号的双引号分隔字符串的并列.虽然您不会按照这条路线处理数据(所有 dquotes 都会丢失),但您可以使用这种观点来进行计数:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '' -- changed
)
, ','
)
测试用例
-- works
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"""data"",and more so",2,"more data,and even more so"', '(^|,)("[^"]*")+(,|$)', '' ), '(^|,)("[^"]*")+(,|$)', '' ), ',' ) from dual;
-- fails
select regexp_count ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
select regexp_count ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
最好用这个
REGEXP_COUNT(REGEXP_REPLACE(text,',".+",', ',,'), ',')
我有一个包含逗号分隔值的文件,如下所示:
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,,
我想统计除引号外的逗号的个数,例如"Allied Martian Banks, P.L.C.".
我知道:
length(i.data_record)-length(replace(i.data_record,',',''))
会 return 逗号的数量,但是与第二行相比,这会在第一行中计算一个额外的逗号,对于我来说,它们应该被算作具有相同的数字。
有什么快速简单的方法可以忽略引号中的逗号吗?
我知道我可以创建一个循环并开始按位分解字符串,计算它们,每当我找到引号时忽略任何逗号,直到找到另一个引号,但是我想知道是否有更简单的方法,无需借助循环即可实现此目的的更简化方法。
非常感谢!
先去掉分隔的内容,再数:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)"[^"]*"(,|$)'
, ''
)
, '(^|,)"[^"]*"(,|$)'
, ''
)
, ','
)
不幸的是,为了正确处理连续的引号分隔字段,需要嵌套 regexp_replace
调用:正则表达式模式会消耗任何分隔逗号,因此不会在后续匹配中考虑。
Oracle 的 regexen 不支持先行运算符,这将是处理这种情况的自然方式。
考虑到 regexp_... 调用的性能影响,您最好使用
length(i.data_record) - length ( replace ( regexp_replace ( i.data_record, '(^|,)"[^"]*"(,|$)', '' ),',','' ) )
警告
此解决方案不处理字段值中的双引号,通常表示为 ""
或 \"
。
前一种情况可以优雅地处理:与其解释引号分隔字段内的 ""
,不如将整个字段内容视为 1 个或多个不包含双引号的双引号分隔字符串的并列.虽然您不会按照这条路线处理数据(所有 dquotes 都会丢失),但您可以使用这种观点来进行计数:
regexp_count (
regexp_replace (
regexp_replace (
i.data_record
, '(^|,)("[^"]*")+(,|$)' -- changed
, '' -- changed
)
, '(^|,)("[^"]*")+(,|$)' -- changed
, '' -- changed
)
, ','
)
测试用例
-- works
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
select regexp_count ( regexp_replace ( regexp_replace ( '1,"""data"",and more so",2,"more data,and even more so"', '(^|,)("[^"]*")+(,|$)', '' ), '(^|,)("[^"]*")+(,|$)', '' ), ',' ) from dual;
-- fails
select regexp_count ( regexp_replace ( '1,"data,and more so","more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
select regexp_count ( regexp_replace ( '1,"data,and more so",2,"more data,and even more so"', '(^|,)"[^"]*"(,|$)', '' ), ',' ) from dual;
最好用这个
REGEXP_COUNT(REGEXP_REPLACE(text,',".+",', ',,'), ',')