编写/解析固定宽度行的文本文件
我刚开始学习Python,想用它来写一些我们供应商需要的复杂EDI内容。
简单来说,他们需要一个80个字符宽的固定格式文本文件,里面有些字段是有数据的,有些则是空白的。我手里有文档,所以我知道每个字段的长度。收到的回复更容易处理,因为里面已经有数据,我可以用Python的“切片”功能来提取我需要的部分,但我不能直接给切片赋值——我试过了,因为这听起来是个好办法,但没成功,因为Python的字符串是不可变的 :)
正如我所说,我真的很新手,但我对学习Python感到兴奋 :) 我该怎么做呢?理想情况下,我希望能说第10到20个字符等于“Foo”,并且它是字符串“Foo”后面加上7个空格(假设这个字段的长度是10),然后把它放进更大的80个字符的字段里,但我不太确定怎么实现我想的这个。
8 个回答
你可以使用 对齐 函数来把一个字符串靠左对齐、靠右对齐或者居中对齐,适应指定的宽度。
'hi'.ljust(10) -> 'hi '
希望我理解你的意思:你想要一种简单的方法来方便地识别每一部分内容,并用一个简单的变量表示,同时输出时要对齐到正确的宽度,对吧?
下面的代码片段可能能满足你的需求:
class FixWidthFieldLine(object):
fields = (('foo', 10),
('bar', 30),
('ooga', 30),
('booga', 10))
def __init__(self):
self.foo = ''
self.bar = ''
self.ooga = ''
self.booga = ''
def __str__(self):
return ''.join([getattr(self, field_name).ljust(width)
for field_name, width in self.fields])
f = FixWidthFieldLine()
f.foo = 'hi'
f.bar = 'joe'
f.ooga = 'howya'
f.booga = 'doin?'
print f
运行后会得到:
hi joe howya doing
这个方法是通过存储一个类级别的变量 fields
来实现的,它记录了每个字段在输出中应该出现的顺序,以及每个字段应该占用的列数。同时,在 __init__
方法中有相应命名的实例变量,最开始设置为空字符串。
__str__
方法会把这些值输出为一个字符串。它使用了一个列表推导式,遍历类级别的 fields
属性,通过名称查找每个字段的实例值,然后根据列数将输出左对齐。最后,得到的字段列表会用一个空字符串连接在一起。
需要注意的是,这个方法并不会解析输入,不过你可以很容易地重写构造函数,让它接受一个字符串,并根据 fields
中的字段和字段宽度来解析列。它也不会检查实例值是否超过了分配的宽度。
你不需要给切片赋值,只需要用 % 格式化
来构建字符串。
下面是一个固定格式的例子,包含3个数据项:
>>> fmt="%4s%10s%10s"
>>> fmt % (1,"ONE",2)
' 1 ONE 2'
>>>
同样的,数据中提供了字段宽度:
>>> fmt2 = "%*s%*s%*s"
>>> fmt2 % (4,1, 10,"ONE", 10,2)
' 1 ONE 2'
>>>
分开数据和字段宽度,并使用 zip()
和 str.join()
的技巧:
>>> widths=(4,10,10)
>>> items=(1,"ONE",2)
>>> "".join("%*s" % i for i in zip(widths, items))
' 1 ONE 2'
>>>