Python按字符位置拆分无分隔固定宽度文本列的方案咨询
固定宽度格式文本读取实现方案
问题本质
你接触的这份文本是固定列宽格式(FWF),没有逗号、制表符这类通用分隔符,列边界完全由固定的字符位置决定,短内容用空格补位对齐。直接用默认按空白分割的pd.read_csv读取,会把列内的补位空格误判成分隔符,最终导致列完全错位。
针对这种格式,pandas本身就提供了专门的读取方法,不需要手动处理分割逻辑,针对10万行、每行120字符的规模,性能完全够用。
实现方案
方案1:基于pandas(适配你现有代码习惯)
字符位置映射对齐
注意Python的字符串索引是从0开始计数的,和你日常描述的“第N个字符”存在1个固定偏移,结合你给出的列规则,对应关系如下:
| 列内容 | 你描述的字符范围 | Python切片对应区间(左闭右开) |
|---|---|---|
| O/L标识 | 第1个字符 | 起始索引0,结束索引1 |
| 年份 | 第2-5个字符 | 起始索引1,结束索引5 |
| 月份名称 | 第6-13个字符 | 起始索引5,结束索引13 |
| 汽车品牌 | 第14-21个字符 | 起始索引13,结束索引21 |
| 句点标识 | 第22个字符 | 起始索引21,结束索引22 |
读取代码实现
不需要手动写分割逻辑,直接调用pandas专属的固定宽度读取接口pd.read_fwf,把整理好的列边界传入即可:
import pandas as pd # 按顺序定义每列的(起始字符索引, 结束字符索引) # 目前先填入你已经明确给出的前5列位置,后续拿到剩余9列的位置,按照同样规则补充进列表即可 column_boundaries = [ (0, 1), # O/L标识列 (1, 5), # 年份列 (5, 13), # 月份列 (13, 21), # 汽车品牌列 (21, 22) # 句点列 ] df = pd.read_fwf( 'text.txt', colspecs=column_boundaries, header=None, # 文件无表头 index_col=0 # 将第1列(O/L标识)设为索引,和你原代码的需求一致 ) # 可手动为列命名,提升可读性 df.columns = ['年份', '月份', '汽车品牌', '句点'] print(df.head())
方案2:纯Python原生实现(不依赖pandas)
如果不想安装pandas,直接逐行按位置切割字符串即可,逻辑非常简单,没有额外依赖:
# 列边界定义和pandas方案完全一致 column_boundaries = [ (0, 1), (1, 5), (5, 13), (13, 21), (21, 22) ] structured_data = [] with open('text.txt', 'r', encoding='utf-8') as f: for line in f: # 去掉行尾换行符,避免干扰最后一列的读取 clean_line = line.rstrip('\n') # 按位置切割每列,同时去掉列前后的补位空格 current_row = [ clean_line[start:end].strip() for start, end in column_boundaries ] structured_data.append(current_row) # 后续可根据需求将结构化数据转成字典、数组或者其他格式 print(structured_data[:5])
常见踩坑提醒
- 不要直接用
str.split(' ')按空格分割,列内部的补位空格不属于内容本身,分割后会产生大量空字符串,直接打乱列的顺序。 - 处理每行内容时记得剥离行尾的换行符,不然会导致最后一列的读取长度超出实际内容范围。
- 计算切片区间时,一定要遵循Python左闭右开的规则,比如长度为4的年份字段,从索引1开始切,结束位置写5而不是4,不然会少读一个字符。
内容的提问来源于stack exchange,提问作者JeannyJ90
相关产品推荐
相关产品推荐

