PySpark按分隔符分割RDD时忽略双引号的正则问题
解决Spark RDD中忽略双引号内逗号的分割问题
嗨,我一眼就看出问题所在了——你用了Python字符串的split()方法,但它根本不会把你写的参数当作正则表达式处理!它只会把整个字符串当作普通分隔符去匹配,而你的正则串显然不会出现在原始数据里,所以自然没分割成功。下面给你两种可行的解决办法:
方法一:用re.split()配合正则表达式分割
首先要导入re模块,re.split()才是支持正则表达式作为分隔符的方法。我们可以用正向预查来精准匹配不在双引号内的逗号:
import re # 创建你定义的基础RDD rdd = sc.parallelize(['"ab,cd",9', 'xyz,6']) # 使用原始字符串r''定义正则,避免转义混乱 split_result = rdd.map(lambda x: re.split(r',(?=(?:[^"]*"[^"]*")*[^"]*$)', x)).collect() print(split_result)
运行后会得到:
[['"ab,cd"', '9'], ['xyz', '6']]
如果想去掉结果里的双引号,只需要加一步字段清理:
split_result = rdd.map(lambda x: [field.strip('"') for field in re.split(r',(?=(?:[^"]*"[^"]*")*[^"]*$)', x)]).collect() print(split_result)
输出就是你想要的:
[['ab,cd', '9'], ['xyz', '6']]
方法二:用re.findall()直接提取目标字段
另一种更直观的思路是直接提取符合要求的字段:要么匹配双引号包裹的内容,要么匹配不含逗号的普通字段,这样可以直接得到干净的结果:
import re rdd = sc.parallelize(['"ab,cd",9', 'xyz,6']) # 正则匹配双引号内的内容,或非逗号字段,再过滤空结果 extract_result = rdd.map(lambda x: [item for sub in re.findall(r'"([^"]*)"|([^,]+)', x) for item in sub if item]).collect() print(extract_result)
输出同样是:
[['ab,cd', '9'], ['xyz', '6']]
正则小解释
- 方法一的正则
r',(?=(?:[^"]*"[^"]*")*[^"]*$)':,定位要分割的逗号(?=...)正向预查确保逗号后面的引号是成对的(也就是逗号不在引号包裹范围内),避免分割引号内的逗号
- 方法二的正则
r'"([^"]*)"|([^,]+)':"([^"]*)"捕获双引号内的所有内容|表示“或”逻辑([^,]+)捕获不含逗号的普通字段
最后用列表推导式过滤掉捕获过程中产生的空字符串,得到最终字段列表。
内容的提问来源于stack exchange,提问作者learning_dev
相关产品推荐
相关产品推荐

