使用Apache Pig处理含特殊逗号分隔符的特定数据文件问题
首先看你的原始CSV数据(注意第二行第三个字段包含逗号且被双引号包裹):
150060275,NON-CRIMINAL,LOST PROPERTY,Monday,01/19/2015,14:00,MISSION,NONE,18TH ST / VALENCIA ST,-122.42158168137,37.7617007179518,"(37.7617007179518, -122.42158168137)",150060275 71000 150098210,ROBBERY,"ROBBERY, BODILY FORCE",Sunday,02/01/2015,15:45,TENDERLOIN,NONE,300 Block of LEAVENWORTH ST,-122.414406029855,37.7841907151119,"(37.7841907151119, -122.414406029855)",15009821003074
你遇到的问题是:第二行第三个字段里的逗号不应该被当作分隔符,但普通的STRPLIT()函数会错误拆分这个字段,导致第一行解析正常但第二行解析结果混乱。
解决思路
这个问题的核心是你的数据遵循标准CSV格式——用双引号包裹包含分隔符的字段,所以最靠谱的方式是使用支持标准CSV解析的工具/函数,而不是手动用STRPLIT()分割。以下是不同场景下的解决方案:
Python/编程语言场景:
直接使用语言内置的CSV解析模块,它们会自动识别双引号包裹的字段,忽略内部的逗号。比如Python的csv模块:import csv # 处理字符串形式的CSV数据 csv_data = """150060275,NON-CRIMINAL,LOST PROPERTY,Monday,01/19/2015,14:00,MISSION,NONE,18TH ST / VALENCIA ST,-122.42158168137,37.7617007179518,"(37.7617007179518, -122.42158168137)",150060275 71000 150098210,ROBBERY,"ROBBERY, BODILY FORCE",Sunday,02/01/2015,15:45,TENDERLOIN,NONE,300 Block of LEAVENWORTH ST,-122.414406029855,37.7841907151119,"(37.7841907151119, -122.414406029855)",15009821003074""" for row in csv.reader(csv_data.splitlines()): print(f"第{row[0]}行的第三个字段:{row[2]}")运行后会正确输出:
第150060275行的第三个字段:LOST PROPERTY
第71000 150098210行的第三个字段:ROBBERY, BODILY FORCESQL/数据仓库场景:
大多数云数据仓库(比如BigQuery、Snowflake)都有内置的CSV解析函数,或者可以用正则匹配不在双引号内的逗号作为分隔符。比如BigQuery的写法:SELECT SPLIT_BY_REGEX(r',(?=(?:[^"]*"[^"]*")*[^"]*$)', raw_line) AS parsed_fields FROM your_dataset.your_table这个正则的逻辑是:只匹配那些后面跟着偶数个双引号的逗号(也就是不在引号包裹范围内的逗号)。
Excel/Google Sheets场景:
使用内置的「文本分列」功能:- 选中数据列,点击「数据」→「文本分列」
- 选择「分隔符号」,点击下一步
- 勾选「逗号」作为分隔符,然后在「文本识别符」处选择「双引号」
- 完成后,带引号的字段会被正确识别为单个单元格。
应急方案:如果必须使用STRPLIT()
如果你因为环境限制只能用STRPLIT(),可以先临时替换掉引号内的逗号,分割后再还原回来。比如在Google Sheets中:
=ARRAYFORMULA( SUBSTITUTE( STRPLIT( SUBSTITUTE(A:A, """ROBBERY, BODILY FORCE""", """ROBBERY_TEMP_PLACEHOLDER"""), "," ), "ROBBERY_TEMP_PLACEHOLDER", "ROBBERY, BODILY FORCE" ) )
但这个方法局限性很大,只适用于已知的特定字段,一旦有其他带逗号的字段就会失效,所以仅作为应急使用。
内容的提问来源于stack exchange,提问作者Abinash Patra

