[英]Parsing data from text file
我有一个文本文件,其内容如下:
******** ENTRY 01 ********
ID: 01
Data1: 0.1834869385E-002
Data2: 10.9598489301
Data3: -0.1091356549E+001
Data4: 715
然后是一个空行,并重复更多类似的块,所有这些块都具有相同的数据字段。
我正在向Python移植一个C ++代码,某个部分逐行获取文件,检测文本标题,然后检测每个字段文本以提取数据。 这根本不像一个智能代码,我认为Python必须有一些库来轻松地解析这样的数据。 毕竟,它几乎看起来像一个CSV!
对此有何看法?
实际上它离CSV非常远。
您可以将该文件用作迭代器; 以下生成器函数生成完整的部分:
def load_sections(filename):
with open(filename, 'r') as infile:
line = ''
while True:
while not line.startswith('****'):
line = next(infile) # raises StopIteration, ending the generator
continue # find next entry
entry = {}
for line in infile:
line = line.strip()
if not line: break
key, value = map(str.strip, line.split(':', 1))
entry[key] = value
yield entry
这会将文件视为迭代器,这意味着任何循环都会将文件前进到下一行。 外环仅用于从一个部分移动到另一个部分; 内在的while
和for
循环完成所有真正的工作; 首先跳过行直到找到****
标题部分(否则丢弃),然后遍历所有非空行以创建一个部分。
在循环中使用该函数:
for section in load_sections(filename):
print section
在文本文件中重复样本数据会导致:
>>> for section in load_sections('/tmp/test.txt'):
... print section
...
{'Data4': '715', 'Data1': '0.1834869385E-002', 'ID': '01', 'Data3': '-0.1091356549E+001', 'Data2': '10.9598489301'}
{'Data4': '715', 'Data1': '0.1834869385E-002', 'ID': '01', 'Data3': '-0.1091356549E+001', 'Data2': '10.9598489301'}
{'Data4': '715', 'Data1': '0.1834869385E-002', 'ID': '01', 'Data3': '-0.1091356549E+001', 'Data2': '10.9598489301'}
如果您愿意,可以添加一些数据转换器; 密钥到可调用的映射可以:
converters = {'ID': int, 'Data1': float, 'Data2': float, 'Data3': float, 'Data4': int}
然后在生成器函数中,而不是entry[key] = value
do entry[key] = converters.get(key, lambda v: v)(value)
。
my_file:
******** ENTRY 01 ********
ID: 01
Data1: 0.1834869385E-002
Data2: 10.9598489301
Data3: -0.1091356549E+001
Data4: 715
ID: 02
Data1: 0.18348674325E-012
Data2: 10.9598489301
Data3: 0.0
Data4: 5748
ID: 03
Data1: 20.1834869385E-002
Data2: 10.954576354
Data3: 10.13476858762435E+001
Data4: 7456
Python脚本:
import re
with open('my_file', 'r') as f:
data = list()
group = dict()
for key, value in re.findall(r'(.*):\s*([\dE+-.]+)', f.read()):
if key in group:
data.append(group)
group = dict()
group[key] = value
data.append(group)
print data
印刷输出:
[
{
'Data4': '715',
'Data1': '0.1834869385E-002',
'ID': '01',
'Data3': '-0.1091356549E+001',
'Data2': '10.9598489301'
},
{
'Data4': '5748',
'Data1': '0.18348674325E-012',
'ID': '02',
'Data3': '0.0',
'Data2': '10.9598489301'
},
{
'Data4': '7456',
'Data1': '20.1834869385E-002',
'ID': '03',
'Data3': '10.13476858762435E+001',
'Data2': '10.954576354'
}
]
一个非常简单的方法可能是
all_objects = []
with open("datafile") as f:
for L in f:
if L[:3] == "***":
# Line starts with asterisks, create a new object
all_objects.append({})
elif ":" in L:
# Line is a key/value field, update current object
k, v = map(str.strip, L.split(":", 1))
all_objects[-1][k] = v
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.