如何用REGEX拆分CSV行:跳过引号内逗号适配两种标题格式
答案
可以通过正则实现该需求,下面提供两种常用实现方案:
方案1:直接匹配所有字段(推荐,自动去除字段外层引号)
使用的正则表达式:(?<=^|,)(?:"([^"]*)"|([^,]*))(?=$|,)
正则解释
(?<=^|,):限定匹配位置必须在行首或者逗号之后,也就是每个字段的起始位置(?:"([^"]*)"|([^,]*)):匹配两种格式的字段:- 带引号的字段:匹配被双引号包裹的内容,自动捕获引号内部的文本(不会带上外层引号)
- 不带引号的字段:匹配所有非逗号的连续字符
(?=$|,):限定匹配位置必须在行尾或者逗号之前,也就是每个字段的结束位置
匹配效果
对两行CSV分别匹配后,得到的捕获结果依次为:
- 第一行:
315、Misérables, Les (1995)、Drama|War - 第二行:
315、Big Bully (1996)、Comedy|Drama
方案2:按有效逗号分割
如果你的使用场景更适合用split(分割)操作,可以使用如下正则匹配需要分割的逗号:,(?=(?:[^"]*"[^"]*")*[^"]*$)
正则解释
该正则只会匹配不在双引号内部的逗号:
核心是后面的正向预查(?=(?:[^"]*"[^"]*")*[^"]*$),验证当前逗号后面的双引号总数是偶数,说明该逗号没有被双引号包裹,属于字段分隔符。
分割效果
对两行CSV分别分割后得到的结果依次为:
- 第一行:
['315', '"Misérables, Les (1995)"', 'Drama|War'],如果不需要外层引号,对第二个字段做一次首尾引号去除即可 - 第二行:
['315', 'Big Bully (1996)', 'Comedy|Drama']
注意事项
上述正则仅适用于字段内部没有转义双引号的场景,如果你的CSV存在"name, ""nickname"""这类转义引号的格式,需要对正则做额外适配,你给出的示例场景可以直接使用上述方案。
内容的提问来源于stack exchange,提问作者Xhuliano98
相关产品推荐
相关产品推荐

