如何用Python筛选CSV指定列的正则匹配行并拆分输出至不同文件?
Python CSV正则筛选与多模式扩展方案
实现代码示例
方法一:使用标准库csv
无需额外依赖,适合轻量级场景:
import csv import re def filter_csv_by_regex(input_path, match_path, no_match_path, code_col, regex_patterns): # 提前编译所有正则,提升匹配效率 compiled_patterns = [re.compile(pattern) for pattern in regex_patterns] with open(input_path, 'r', newline='', encoding='utf-8') as infile, \ open(match_path, 'w', newline='', encoding='utf-8') as match_file, \ open(no_match_path, 'w', newline='', encoding='utf-8') as no_match_file: reader = csv.DictReader(infile) match_writer = csv.DictWriter(match_file, fieldnames=reader.fieldnames) no_match_writer = csv.DictWriter(no_match_file, fieldnames=reader.fieldnames) # 写入表头 match_writer.writeheader() no_match_writer.writeheader() for row in reader: code = row.get(code_col, '') # 检查是否匹配任意一个正则模式 is_match = any(pattern.match(code) for pattern in compiled_patterns) match_writer.writerow(row) if is_match else no_match_writer.writerow(row) # 调用示例 if __name__ == "__main__": regex_list = [ r'[0-9][0-9][A-Z]', r'[0-9][0-9][A-Z] [0-9][0-9][A-Z]' ] filter_csv_by_regex( input_path='input.csv', match_path='matched_rows.csv', no_match_path='unmatched_rows.csv', code_col='Code', regex_patterns=regex_list )
方法二:使用pandas(高效处理大文件)
借助向量化操作,适合数据量较大的场景:
import pandas as pd import re def filter_csv_with_pandas(input_path, match_path, no_match_path, code_col, regex_patterns): # 合并正则为单一模式,用|实现"任意匹配"逻辑 combined_pattern = '|'.join(regex_patterns) df = pd.read_csv(input_path) match_mask = df[code_col].str.match(combined_pattern, na=False) df[match_mask].to_csv(match_path, index=False) df[~match_mask].to_csv(no_match_path, index=False) # 调用示例 if __name__ == "__main__": regex_list = [ r'[0-9][0-9][A-Z]', r'[0-9][0-9][A-Z] [0-9][0-9][A-Z]' ] filter_csv_with_pandas( input_path='input.csv', match_path='matched_rows.csv', no_match_path='unmatched_rows.csv', code_col='Code', regex_patterns=regex_list )
关于正则列表的扩展性问题
采用正则列表的方式非常便于后续扩展,核心原因包括:
- 新增规则只需在列表中添加字符串,无需修改核心筛选逻辑,完全符合开闭原则
- 模式可集中管理,比如单独存放在配置文件或常量模块中,维护成本低
- 逻辑调整灵活:如果需要从"匹配任意模式"改成"匹配所有模式",只需把判断逻辑的
any换成all,模式列表本身无需改动 - 支持临时启用/禁用规则,直接注释列表中的对应项即可
内容的提问来源于stack exchange,提问作者kdawg
相关产品推荐
相关产品推荐

