0

0

Python教程:定制化解析复杂空格分隔文本并生成CSV

DDD

DDD

发布时间:2025-10-31 10:38:19

|

884人浏览过

|

来源于php中文网

原创

Python教程:定制化解析复杂空格分隔文本并生成CSV

当面对格式不规范、空格分隔的文本文件时,标准的数据导入库如pandas可能无法有效处理。本教程将指导您如何利用python正则表达式,通过定制化的解析逻辑,识别并区分字段分隔符与数据内部的空格,从而成功地将此类“脏数据”转换为结构化的csv文件。

在数据处理的实践中,我们经常会遇到格式不规范的文本文件。这类文件通常使用不规则数量的空格来分隔字段,甚至在数据字段内部也可能包含空格,这使得传统的 pandas.read_csv 等方法难以直接处理。例如,尝试使用制表符 (sep='\t') 或固定数量空格 (sep=r"\s{2,}") 作为分隔符,往往会导致列错位、数据丢失或解析错误。为了有效地将这类“坏”文本文件转换为结构化的CSV格式,我们需要编写自定义的Python解析逻辑。

理解“坏”文本文件的挑战

问题中提供的文本数据示例很好地说明了这类文件带来的挑战:

  • 不一致的空格长度: 不同字段之间分隔的空格数量不固定,这使得无法简单地通过固定宽度或统一的分隔符进行分割。
  • 数据内部的空格: 某些字段(例如 Message 字段)本身包含两个或更多连续的空格(如“Rejected at level”中的“at”和“level”之间),这极易与字段分隔符混淆,导致错误的列分割。
  • 空行: 文件中可能包含空行,需要被正确识别和忽略。
  • 缺失值: 某些字段可能为空,表现为连续的多个空格,其长度可能与字段分隔符的长度相似。

定制化解析方案:Python与正则表达式

针对这类复杂场景,最有效的方法是采用逐行读取文件,并结合正则表达式进行精细化匹配和替换的策略。核心思想是:识别不同长度的连续空格所代表的含义——究竟是字段分隔符,还是数据本身的一部分。

以下是实现这一目标的核心Python代码,并附带详细解释:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载

立即学习Python免费学习笔记(深入)”;

import re
import csv

def parse_bad_txt_to_table(filepath):
    """
    解析不规范的空格分隔文本文件,并将其转换为一个列表的列表(表格形式)。

    Args:
        filepath (str): 待解析的文本文件路径。

    Returns:
        list[list[str]]: 解析后的数据表格,每个内部列表代表一行。
    """
    table = []
    try:
        with open(filepath, 'r', encoding='utf-8') as f:
            lines = f.readlines()
    except FileNotFoundError:
        print(f"错误:文件 '{filepath}' 未找到。")
        return []
    except Exception as e:
        print(f"读取文件时发生错误:{e}")
        return []

    for i, line in enumerate(lines):
        line = line.rstrip('\n') # 移除行尾的换行符

        if i == 0:
            # 第一行:标题行。假设标题字段之间不会有“假分隔符”,
            # 故可以安全地按2个或更多空格分割。
            row = re.split(r' {2,}', line)
            table.append(row)
            continue

        if not line.strip(): # 检查是否为空行(包括只含空格的行)
            # 忽略空行,或者根据需要进行特定处理
            continue

        # 对于数据行,我们需要更复杂的逻辑来区分字段分隔符和数据内部的空格
        def replfunc(match_obj):
            """
            根据匹配到的连续空格的长度,决定是替换为单个空格(数据内部)
            还是一个或多个制表符(字段分隔符)。
            """
            L = len(match_obj.group(0)) # 获取匹配到的连续空格的长度

            # 特殊情况处理:识别数据内部的特定空格模式。
            # 示例中 "Rejected at  level." 内部有2个空格,这不应被视为分隔符。
            start, end = match_obj.span()
            if L == 2 and line[:start].endswith('Rejected at') and line[end:].startswith('level.'):
                return ' ' # 将其替换为单个空格,保留在数据内部

            # 其他连续空格被视为字段分隔符,根据其长度映射为不同数量的制表符。
            # 这里的映射规则需要根据实际数据进行观察、分析和调整。
            if L < 2:
                # 理论上不应出现少于2个空格被视为分隔符的情况,否则与数据内部空格冲突。
                # 如果出现,保持不变或抛出警告。
                return match_obj.group(0)
            elif 2 <= L <= 12: # 2到12个空格,替换为单个制表符
                return '\t'
            elif L == 17: # 17个空格,替换为两个制表符(表示中间可能存在一个空字段)
                return '\t\t'
            elif L == 43: # 43个空格,替换为三个制表符
                return '\t\t\t'
            elif L == 61: # 61个空格,替换为五个制表符
                return '\t\t\t\t\t'
            elif L == 120 or L == 263: # 其他特定长度的空格,替换为单个制表符
                return '\t'
            else:
                # 如果遇到未预料的空格长度,可以标记出来以便调试和规则完善。
                # print(f"警告: 未处理的空格长度 {L} 在行 {i+1}: '{line}'")
                return '\t' # 默认替换为单个制表符,可能需要调整

        # 使用re.sub结合replfunc替换连续空格,将字段分隔符统一为制表符
        tabbed_line = re.sub(r'\s{2,}', replfunc, line)
        row = tabbed_line.split('\t') # 依据制表符分割字段
        table.append(row)
    return table

def write_table_to_csv(table_data, output_filepath):
    """
    将解析后的表格数据写入CSV文件。

    Args:
        table_data (list[list[str]]): 待写入的表格数据。
        output_filepath (str): 输出CSV文件的路径。
    """
    try:
        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}'")
    except Exception as e:
        print(f"写入CSV文件时发生错误:{e}")

# --- 示例使用 ---
input_file = 'input.txt'  # 假设您的原始文本文件名为input.txt
output_file = 'Report.csv'

# 1. 解析文本文件
parsed_data_table = parse_bad_txt_to_table(input_file)

# 2. 将解析后的数据写入CSV文件
if parsed_data_table:
    write_table_to_csv(parsed_data_table, output_file)

# ---------------------------
# 以下代码用于在控制台美观地打印解析结果,便于检查(可选)
def print_formatted_table(table_data):
    """
    在控制台以对齐的方式打印表格数据。
    """
    if not table_data:
        print("无数据可显示。")
        return

    # 计算每列的最大宽度
    max_n_fields = max(len(row) for row in table_data)
    field_widths = [0] * max_n_fields
    for row in table_data:
        for j, field in enumerate(row):
            if j < max_n_fields:
                field_widths[j] = max(field_widths[j], len(field))

    # 打印表格
    for row in table_data:
        for j, field in enumerate(row):
            if j < max_n_fields:
                print(field.ljust(field_widths[j]), end='|')
        print()

# print("\n解析结果预览:")
# print_formatted_table(parsed_data_table)

代码解析与注意事项

  1. 逐行处理: 文件被逐行读取,这允许我们根据行号(例如,标题行与数据行)应用不同的解析规则。rstrip('\n') 用于移除行尾的换行符。
  2. replfunc 的核心作用: 这是整个解析逻辑的关键。re.sub(r'\s{2,}', replfunc, line) 会查找所有连续两个或更多空格的序列 (\s{2,}),并对每个匹配项调用 replfunc 函数。
  3. 区分数据内部空格与分隔符: replfunc 首先检查一个特定的模式("Rejected at level."),如果匹配,则将两个空格替换为单个空格,从而保留其作为数据的一部分。这种模式识别是针对特定业务逻辑的定制化处理,对于不同的文件,需要根据实际情况调整。
  4. 动态映射空格长度到制表符: 对于其他连续空格,replfunc 根据其长度将其替换为一个或多个制表符 (\t)。例如,如果 L 是 17,它被替换为两个制表符,这暗示了在原始文本中可能存在一个空字段。这些映射规则 (L == 17 对应 \t\t 等) 是通过观察原始数据中不同字段分隔符的宽度总结出来的,并且可能需要根据实际文件的具体情况进行微调。这是最需要人工分析和调整的部分。
  5. split('\t'): 一旦所有字段分隔符都被统一替换为制表符,就可以简单地使用 split('\t') 来获取最终的字段列表。
  6. CSV写入: 使用Python内置的 csv 模块将解析后的数据写入CSV文件。newline='' 参数在 open() 中是重要的,它能防止在Windows系统上写入额外的空行。
  7. 通用性限制: 这种方法高度依赖于对特定“坏”文件格式的观察和理解。如果文件格式稍有变化,replfunc 中的逻辑(特别是空格长度的映射)可能需要重新调整。对于高度不规则的文件,甚至可能需要更复杂的有限状态机或机器学习方法来自动识别模式。
  8. 错误处理: 示例代码中包含文件读取和写入的 try-except 块,以提高程序的健壮性。replfunc 中的 else 分支可以用于处理未预期的空格长度,这对于调试和发现新的格式模式非常有用。

总结

处理格式不规范的文本文件是一项常见的挑战,尤其当标准库无法直接胜任时。通过Python结合正则表达式的定制化解析,我们可以精确控制如何识别和处理字段分隔符,即使在数据内部存在与分隔符相似的模式。虽然这种方法需要根据具体文件格式进行细致的调整和测试,但它为解决复杂的数据清洗问题提供了一个强大而灵活的工具。在实际应用中,建议对数据进行充分的探索性分析,以建立准确的解析规则,并考虑将解析逻辑模块化,以便于维护和复用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

515

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

251

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

749

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

215

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

351

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

236

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

533

2023.12.06

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

30

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号