我是Python的新手,我需要做一个解析练习。我有一个文件,我需要解析它(只是标题),但是在这个过程之后,我需要保持文件格式相同,扩展名相同,并且在磁盘中的相同位置,但只有差异新标题..
我试过这段代码......
for line in open ('/home/name/db/str/dir/numbers/str.phy'):
if line.startswith('ENS'):
linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
print linepars
..它完成了这项工作,但我不知道如何用新的解析“覆盖”文件。
答案 0 :(得分:4)
最简单的方法,但不是最有效的(到目前为止,特别是对于长文件)将重写完整的文件。
您可以通过打开第二个文件句柄并重写每一行来完成此操作,但在标题的情况下,您将编写已解析的标题。例如,
fr = open('/home/name/db/str/dir/numbers/str.phy')
fw = open('/home/name/db/str/dir/numbers/str.phy.parsed', 'w') # Name this whatever makes sense
for line in fr:
if line.startswith('ENS'):
linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
fw.write(linepars)
else:
fw.write(line)
fw.close()
fr.close()
编辑:请注意,这不使用readlines()
,因此它的内存效率更高。它也不会存储每个输出行,而是一次只存储一个输出行,立即将其写入文件。
就像一个很酷的技巧,你可以在输入文件上使用with
语句,以避免必须关闭它(Python 2.5 +):
fw = open('/home/name/db/str/dir/numbers/str.phy.parsed', 'w') # Name this whatever makes sense
with open('/home/name/db/str/dir/numbers/str.phy') as fr:
for line in fr:
if line.startswith('ENS'):
linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
fw.write(linepars)
else:
fw.write(line)
fw.close()
P.S。欢迎: - )
答案 1 :(得分:2)
正如其他人在这里所说,你想打开一个文件并使用该文件对象的.write()
方法。
最好的方法是打开一个额外的文件进行写作:
import os
current_cfg = open(...)
parsed_cfg = open(..., 'w')
for line in current_cfg:
new_line = parse(line)
print new_line
parsed.cfg.write(new_line + '\n')
current_cfg.close()
parsed_cfg.close()
os.rename(....) # Rename old file to backup name
os.rename(....) # Rename new file into place
此外,我建议查看tempfile
模块,并使用其中一种方法命名新文件或打开/创建它。我个人赞成将新文件放在与现有文件相同的目录中,以确保os.rename
能够原子地工作(命名的配置文件将保证指向旧文件或新文件;否则它会指向部分写入/复制的文件。)
答案 2 :(得分:0)
以下代码完成工作 我的意思是它会覆盖文件ON ONESELF;这就是OP所要求的。这是可能的,因为转换只是删除字符,因此写入的文件指针 fo 始终是文件的指针 fi 读取。
import re
regx = re.compile('\AENS([A-Z]+)0+([0-9]{6})')
with open('bomo.phy','rb+') as fi, open('bomo.phy','rb+') as fo:
fo.writelines(regx.sub('\\1\\2',line) for line in fi)
我认为写操作不是由操作系统一次一行执行,而是通过缓冲区执行。因此在写入转换行池之前会读取几行。这就是我的想法。
答案 3 :(得分:-1)
newlines = []
for line in open ('/home/name/db/str/dir/numbers/str.phy').readlines():
if line.startswith('ENS'):
linepars = re.sub ('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
newlines.append( linepars )
open ('/home/name/db/str/dir/numbers/str.phy', 'w').write('\n'.join(newlines))
答案 4 :(得分:-1)
(旁注:当然如果您正在使用大型文件,您应该知道所需的优化级别可能取决于您的情况。本质上Python非常非延迟评估。以下解决方案不是很好选择是否要解析大型文件,例如数据库转储或日志,但是一些调整(例如嵌套with
子句并使用延迟生成器或逐行算法)可以允许O(1) - 内存行为。)
targetFile = '/home/name/db/str/dir/numbers/str.phy'
def replaceIfHeader(line):
if line.startswith('ENS'):
return re.sub('ENS([A-Z]+)0+([0-9]{6})','\\1\\2',line)
else:
return line
with open(targetFile, 'r') as f:
newText = '\n'.join(replaceIfHeader(line) for line in f)
try:
# make backup of targetFile
with open(targetFile, 'w') as f:
f.write(newText)
except:
# error encountered, do something to inform user where backup of targetFile is
编辑:感谢杰夫的建议