
本文详细介绍了如何使用python处理结构不规范、空格分隔的文本文件并将其转换为标准的csv格式。针对传统方法失效的复杂场景,教程通过自定义正则表达式解析逻辑,精准识别字段分隔符与字段内空格,提供了健壮的数据清洗和转换方案,尤其适用于具有挑战性的非标准数据源。
在数据处理中,我们经常会遇到格式不规范的文本文件。例如,一些文件可能使用空格作为字段分隔符,但这些空格的长度不固定,甚至字段内部也可能包含多个空格,导致传统的数据读取方法(如 pandas.read_csv 配合 sep='\t' 或 sep=r'\s{2,}')无法正确解析。这种“坏”文件通常需要更高级的自定义解析策略。
考虑以下示例数据,它展示了典型的非标准空格分隔格式:
HP TRA ID CL ID IN/EId No Loop Element Name Freq STATUS Error Severity Error ID Message Report Source 13ZI 20712800032 1 Denied Error HP_DOSOlderTh Date of service is older than 12 months HP 13ZI 20712800032 1 1 Rejected Error CA16 Rejected at level. DupKeyID:0 is a Rejected of DupKeyID:0 from EncounterID:15C7XE9GV00 Claim ID:P_20712800032ALPHA_1649845496_19961109508100_716. HP
在此示例中,字段间的空格数量不一致,且“Message”字段内可能包含“Rejected at level.”这样的双空格,这使得简单的分隔符识别变得复杂。
面对此类文件,最有效的方法是逐行读取文件内容,并利用正则表达式(Regular Expressions)进行精细化匹配和替换,从而将不规则的空格分隔符统一转换为标准的制表符(\t)或其他固定分隔符,然后再进行分割。
立即学习“Python免费学习笔记(深入)”;
replfunc 是一个传递给 re.sub() 的回调函数,它在每次正则表达式 r'\s{2,}' 匹配到两个或更多连续空格时被调用。该函数的核心逻辑是根据匹配到的空格长度及其上下文来决定如何替换。
识别字段内空格: 例如,在“Rejected at level.”中,“at”和“level”之间的两个空格是字段内容的一部分,不应作为分隔符。replfunc 通过检查匹配位置的上下文(line[:start].endswith('Rejected at') 和 line[end:].startswith('level.'))来识别这种情况,并将其替换为单个空格,从而保持字段内容的完整性。
映射不同长度的空格为分隔符: 对于其他情况,不同长度的连续空格被视为字段分隔符。由于原始文件中的字段对齐方式不规则,可能需要根据空格的长度来推断它代表一个字段分隔符还是多个空字段。例如:
通过这种方式,所有不规则的空格分隔符都被统一转换为制表符,然后就可以使用 split('\t') 轻松地将行分割成字段列表。
以下代码演示了如何使用上述策略解析非标准文本文件并将其转换为一个列表的列表(table),其中每个内部列表代表一行数据。
import re
import pandas as pd
import csv
def parse_bad_txt_to_table(filepath):
    """
    解析非标准空格分隔的文本文件,并将其转换为一个列表的列表。
    """
    table = []
    with open(filepath, 'r', encoding='utf-8') as f:
        lines = f.readlines()
    for i, line in enumerate(lines):
        line = line.rstrip('\n') # 移除行末换行符
        if i == 0:
            # 头部(标题行)处理:假设头部字段间至少有两个空格
            row = re.split(r' {2,}', line)
            table.append(row)
            continue
        if not line.strip():
            # 空白行处理:跳过
            continue
        # 数据行处理:使用 replfunc 替换不规则空格
        def replfunc(mo):
            L = len(mo.group(0)) # 匹配到的空格长度
            start, end = mo.span()
            # 特殊情况:处理字段内的双空格,如 "Rejected at  level."
            if L == 2:
                if (line[:start].endswith('Rejected at') and
                    line[end:].startswith('level.')):
                    return ' ' # 替换为单个空格,保持字段完整性
            # 其他情况:根据空格长度替换为制表符
            # 这些长度是根据示例数据推断的启发式规则,可能需要根据实际文件调整
            if L < 2:
                # 理论上不应该匹配到小于2个空格,除非正则表达式有变
                return mo.group(0)
            elif 2 <= L <= 12:
                return '\t'
            elif L == 17:
                return '\t\t' # 示例中可能代表两个空字段
            elif L == 43:
                return '\t\t\t' # 示例中可能代表三个空字段
            elif L == 61:
                return '\t\t\t\t\t' # 示例中可能代表五个空字段
            elif L == 120 or L == 263:
                return '\t'
            else:
                # 如果遇到未知的空格长度,可以根据需要处理,例如抛出异常或返回原始空格
                print(f"警告: 遇到未知空格长度 {L} 在行: {line}")
                return f'<{L}>' # 标记未知长度,方便调试
        tabbed_line = re.sub(r'\s{2,}', replfunc, line)
        row = tabbed_line.split('\t')
        # 清理行尾可能多余的空字符串(如果原始行尾有多余分隔符)
        row = [field.strip() for field in row if field.strip() or field == '']
        table.append(row)
    return table
# 假设你的文件名为 'input.txt'
input_filepath = 'input.txt'
parsed_data = parse_bad_txt_to_table(input_filepath)
# 打印解析结果(可选)
# for r in parsed_data:
#     print(r)将 parse_bad_txt_to_table 函数返回的 table(一个列表的列表)转换为CSV文件有多种方法。最常见且推荐的方式是使用 pandas 库,因为它提供了强大的数据结构和方便的CSV写入功能。
# ... (接上面的解析代码) ...
def save_table_to_csv(table_data, output_filepath):
    """
    将解析后的数据保存为CSV文件。
    """
    if not table_data:
        print("没有数据可写入CSV。")
        return
    # 确保所有行的字段数量一致,不足的用空字符串填充
    # 找到最大字段数
    max_cols = max(len(row) for row in table_data)
    processed_table = []
    for row in table_data:
        # 填充或截断行以匹配最大列数
        if len(row) < max_cols:
            processed_table.append(row + [''] * (max_cols - len(row)))
        else:
            processed_table.append(row[:max_cols]) # 截断多余的字段(如果存在)
    # 使用 pandas 写入 CSV
    df = pd.DataFrame(processed_table[1:], columns=processed_table[0])
    df.to_csv(output_filepath, index=False, encoding='utf-8')
    print(f"数据已成功保存到 {output_filepath}")
# 将解析后的数据保存为 CSV
output_filepath = 'Report.csv'
save_table_to_csv(parsed_data, output_filepath)
# 也可以使用 Python 内置的 csv 模块
# def save_table_to_csv_with_csv_module(table_data, output_filepath):
#     if not table_data:
#         print("没有数据可写入CSV。")
#         return
#     with open(output_filepath, 'w', newline='', encoding='utf-8') as csvfile:
#         csv_writer = csv.writer(csvfile)
#         csv_writer.writerows(table_data)
#     print(f"数据已成功保存到 {output_filepath} (使用csv模块)")
# save_table_to_csv_with_csv_module(parsed_data, 'Report_csv_module.csv')处理非标准文本文件并将其转换为规范的CSV格式是一项常见但具有挑战性的任务。通过结合Python的强大文件I/O能力和正则表达式的灵活匹配替换功能,我们可以构建自定义的解析逻辑,有效应对复杂多变的文本数据格式。本教程提供的方法和示例代码展示了如何针对特定数据模式进行精确控制,从而将“脏”数据转化为可用的结构化信息。记住,理解数据本身的模式是成功的关键,而代码只是实现这一理解的工具。
以上就是Python教程:利用正则表达式处理复杂文本文件并高效转换为CSV的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
 
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号