我是Python的新手,我正在使用它来编写供应商需要的一些毛茸茸的EDI。
基本上他们需要一个80个字符的固定宽度文本文件,该字段的某些“块”包含数据,而其他文件则留空。我有文档,所以我知道每个“块”的长度是多少。我得到的响应更容易解析,因为它已经有数据,我可以使用Python的“切片”来提取我需要的东西,但是我不能分配给切片 - 我已经尝试了,因为它听起来像一个好的解决方案,它不起作用,因为Python字符串是不可变的:)
就像我说我真的是Python的新手,但我很高兴学习它:)我会怎么做呢?理想情况下,我希望能够说范围10-20等于“Foo”,并且它是带有7个额外空白字符的字符串“Foo”(假设所述字段的长度为10)并且具有80字符大字体的一部分,但我不知道如何做我正在思考的事情。
答案 0 :(得分:17)
您不需要分配切片,只需使用% formatting
构建字符串。
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'
>>>
答案 1 :(得分:8)
您可以使用justify函数左对齐,右对齐并将字符串置于给定宽度的字段中。
'hi'.ljust(10) -> 'hi '
答案 2 :(得分:7)
希望我明白你在寻找什么:通过一个简单的变量方便地识别线的每个部分,但输出填充到正确的宽度?
下面的代码段可能会为您提供您想要的内容
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 :(得分:1)
我知道这个帖子已经很老了,但是我们使用了一个名为django-copybook的库。它与django(不再)无关。我们用它来介于固定宽度的cobol文件和python之间。您创建一个类来定义固定宽度记录布局,并且可以在键入的python对象和固定宽度文件之间轻松移动:
USAGE:
class Person(Record):
first_name = fields.StringField(length=20)
last_name = fields.StringField(length=30)
siblings = fields.IntegerField(length=2)
birth_date = fields.DateField(length=10, format="%Y-%m-%d")
>>> fixedwidth_record = 'Joe Smith 031982-09-11'
>>> person = Person.from_record(fixedwidth_record)
>>> person.first_name
'Joe'
>>> person.last_name
'Smith'
>>> person.siblings
3
>>> person.birth_date
datetime.date(1982, 9, 11)
它还可以处理类似于Cobol的OCCURS功能的情况,例如当特定部分重复X次时
答案 4 :(得分:0)
解析你的问题有点困难,但我收集到你正在接收一个文件或类文件对象,阅读它,并用一些业务逻辑结果替换一些值。这是对的吗?
克服字符串不变性的最简单方法是编写一个新字符串:
# Won't work:
test_string[3:6] = "foo"
# Will work:
test_string = test_string[:3] + "foo" + test_string[6:]
话虽如此,听起来你对这个字符串做一些事情很重要,但我不确定那是什么意思。您是否将其写回输出文件,尝试编辑文件或其他内容?我提出这个问题是因为创建一个新字符串(碰巧与旧字符串具有相同的变量名)的行为应该强调在转换后执行显式写操作的必要性。
答案 5 :(得分:0)
您可以将字符串转换为列表并执行切片操作。
>>> text = list("some text")
>>> text[0:4] = list("fine")
>>> text
['f', 'i', 'n', 'e', ' ', 't', 'e', 'x', 't']
>>> text[0:4] = list("all")
>>> text
['a', 'l', 'l', ' ', 't', 'e', 'x', 't']
>>> import string
>>> string.join(text, "")
'all text'
答案 6 :(得分:0)
很容易编写函数来“修改”字符串。
def change(string, start, end, what):
length = end - start
if len(what)<length: what = what + " "*(length-len(what))
return string[0:start]+what[0:length]+string[end:]
用法:
test_string = 'This is test string'
print test_string[5:7]
# is
test_string = change(test_string, 5, 7, 'IS')
# This IS test string
test_string = change(test_string, 8, 12, 'X')
# This IS X string
test_string = change(test_string, 8, 12, 'XXXXXXXXXXXX')
# This IS XXXX string
答案 7 :(得分:0)
我使用了Jarret Hardie的例子并略微修改了它。这允许选择文本对齐类型(左,右或居中)。
class FixedWidthFieldLine(object):
def __init__(self, fields, justify = 'L'):
""" Returns line from list containing tuples of field values and lengths. Accepts
justification parameter.
FixedWidthFieldLine(fields[, justify])
fields = [(value, fieldLenght)[, ...]]
"""
self.fields = fields
if (justify in ('L','C','R')):
self.justify = justify
else:
self.justify = 'L'
def __str__(self):
if(self.justify == 'L'):
return ''.join([field[0].ljust(field[1]) for field in self.fields])
elif(self.justify == 'R'):
return ''.join([field[0].rjust(field[1]) for field in self.fields])
elif(self.justify == 'C'):
return ''.join([field[0].center(field[1]) for field in self.fields])
fieldTest = [('Alex', 10),
('Programmer', 20),
('Salem, OR', 15)]
f = FixedWidthFieldLine(fieldTest)
print f
f = FixedWidthFieldLine(fieldTest,'R')
print f
返回:
Alex Programmer Salem, OR
Alex Programmer Salem, OR