寻求Python代码:处理行尾CRLF并统计管道分隔文件的分隔符
嘿,手动处理这种文件简直是噩梦!我太懂你这种感受了——带双引号文本限定符的管道分隔文件,字段里藏着CRLF,直接按行读全乱套,还得手动找,效率低到爆炸。
我给你两个解决方案,优先推荐用Python标准库的csv模块,省心又靠谱;如果你想自己实现逻辑,也给你写了手动处理的版本,顺便帮你统计每条记录的分隔符数量。
方案一:用csv模块(推荐)
Python的csv模块天生就支持处理带文本限定符的分隔文件,能自动识别字段内的换行符,完全不用自己写复杂的状态判断。下面的代码既能统计每条有效记录的分隔符数量,还能把字段内的CRLF替换成你想要的内容(比如空格),输出整齐的文件:
import csv # 替换成你的输入输出文件路径 input_path = "your_source_file.txt" output_path = "cleaned_result.txt" # 用来存储每条记录的分隔符统计结果 delimiter_stats = [] with open(input_path, 'r', newline='', encoding='utf-8') as infile, \ open(output_path, 'w', newline='', encoding='utf-8') as outfile: # 配置读取器:指定管道为分隔符,双引号为文本限定符,开启双引号转义(处理字段内的双引号) reader = csv.reader(infile, delimiter='|', quotechar='"', doublequote=True) # 配置写入器:保持和原文件一致的格式 writer = csv.writer(outfile, delimiter='|', quotechar='"', doublequote=True, quoting=csv.QUOTE_NONNUMERIC) for record_idx, record in enumerate(reader, start=1): # 分隔符数量 = 字段数 - 1(每个字段之间一个管道符) sep_count = len(record) - 1 delimiter_stats.append(f"第 {record_idx} 条记录:{sep_count} 个分隔符") # 把字段内的CRLF替换成空格(你也可以换成\n或者其他字符) cleaned_record = [field.replace('\r\n', ' ') for field in record] # 写入处理后的记录 writer.writerow(cleaned_record) # 打印统计结果 print("=== 分隔符数量统计 ===") for stat in delimiter_stats: print(stat)
代码说明:
newline=''是必须的,让csv模块自己处理行结束符,不管是CRLF还是LF都能正确识别。doublequote=True会自动处理字段内的双引号(比如原文件里的"Could even have ""CRLF included """会被正确解析为字段内容),如果你的文件用反斜杠转义双引号,把这个参数改成escapechar='\\'就行。- 统计分隔符数量就是简单的
len(record)-1,因为每条记录的字段数减一就是管道符的数量,精准又方便。
方案二:手动实现状态机(适合学习或特殊需求)
如果你不想依赖csv模块,也可以用状态机的思路自己处理,核心是跟踪当前是否处于双引号包裹的字段内:
input_path = "your_source_file.txt" output_path = "cleaned_result.txt" delimiter_stats = [] with open(input_path, 'r', encoding='utf-8') as infile, \ open(output_path, 'w', encoding='utf-8') as outfile: full_content = infile.read() current_record = [] current_field = [] in_quote = False record_num = 1 idx = 0 content_len = len(full_content) while idx < content_len: char = full_content[idx] if char == '"': # 遇到双引号,切换是否在字段内的状态 in_quote = not in_quote current_field.append(char) idx += 1 elif char == '|' and not in_quote: # 遇到分隔符且不在引号内,结束当前字段 current_record.append(''.join(current_field)) current_field = [] idx += 1 elif char == '\r' and idx + 1 < content_len and full_content[idx+1] == '\n': # 遇到CRLF if in_quote: # 字段内的CRLF,替换成空格 current_field.append(' ') idx += 2 else: # 记录结束,处理当前记录 current_record.append(''.join(current_field)) sep_count = len(current_record) - 1 delimiter_stats.append(f"第 {record_num} 条记录:{sep_count} 个分隔符") # 格式化写入记录(处理双引号转义) cleaned_fields = [] for field in current_record: # 把字段内的"换成"",符合文本限定符规则 escaped_field = field.replace('"', '""') cleaned_fields.append(f'"{escaped_field}"') outfile.write('|'.join(cleaned_fields) + '\r\n') # 重置状态 current_record = [] current_field = [] record_num += 1 idx += 2 else: # 普通字符,加入当前字段 current_field.append(char) idx += 1 # 处理最后一条未结束的记录 if current_field or current_record: current_record.append(''.join(current_field)) sep_count = len(current_record) - 1 delimiter_stats.append(f"第 {record_num} 条记录:{sep_count} 个分隔符") cleaned_fields = [] for field in current_record: escaped_field = field.replace('"', '""') cleaned_fields.append(f'"{escaped_field}"') outfile.write('|'.join(cleaned_fields) + '\r\n') # 打印统计结果 print("=== 分隔符数量统计 ===") for stat in delimiter_stats: print(stat)
代码说明:
- 逐字符遍历整个文件内容,通过
in_quote变量跟踪是否在双引号包裹的字段内。 - 只有当不在引号内时,CRLF才会被视为记录结束标记;在引号内时,CRLF会被替换成空格(你可以根据需求修改)。
- 同样通过
len(current_record)-1统计分隔符数量,逻辑和csv模块一致。
不管用哪个方案,都能帮你彻底摆脱手动处理的痛苦,而且统计分隔符数量的需求也完美满足。
内容的提问来源于stack exchange,提问作者binway
相关产品推荐
相关产品推荐

