你的代码已经删除了第一个字符。我将确切地保存了你的代码,分别命名为 dupy.py
和 dupy.txt
,然后运行了 python dupy.py dupy.txt
,结果如下:
from sys import argv
run, filename = argv
f = open(filename, 'a+')
f.seek(0)
lines = f.readlines()
for line in lines:
f.write(line[1:])
f.close()
rom sys import argv
un, filename = argv
= open(filename, 'a+')
.seek(0)
ines = f.readlines()
or line in lines:
f.write(line[1:])
.close()
它并不是复制整行; 它是复制已去除其第一个字符的行。
但根据您问题的初步陈述,似乎您想要覆盖这些行,而不是追加新副本。为了做到这一点,不要使用append
模式。先读取文件,然后再写入文件:
from sys import argv
run, filename = argv
f = open(filename)
lines = f.readlines()
f.close()
f = open(filename, 'w')
for line in lines:
f.write(line[1:])
f.close()
或者,你也可以写一个新文件,然后在完成时将其移动到原始文件的顶部。
import os
from sys import argv
run, filename = argv
fin = open(filename)
fout = open(filename + '.tmp', 'w')
lines = f.readlines()
for line in lines:
fout.write(line[1:])
fout.close()
fin.close()
os.rename(filename + '.tmp', filename)
(请注意,此版本不能直接在Windows上运行,但比实际的跨平台版本简单;如果您需要在Windows上运行,请告诉我,我可以解释如何操作。)
通过使用
with
语句、直接对文件进行循环而不是调用
readlines
以及使用
tempfile
,可以使代码更加简洁、健壮和高效。
import tempfile
from sys import argv
run, filename = argv
with open(filename) as fin, tempfile.NamedTemporaryFile(delete=False) as fout:
for line in fin:
fout.write(line[1:])
os.rename(fout.name, filename)
在大多数平台上,这可以保证“原子写入”——当您的脚本完成时,甚至在运行过程中有人拔掉插头,该文件要么被新版本替换,要么不变;它不会以不可恢复的垃圾形式半途覆盖。
同样的方法在Windows上不起作用。没有太多的工作,就无法在Windows上实现这种“写入临时文件并重命名”的算法。但是只需要额外做一点工作,就可以接近实现。
with open(filename) as fin, tempfile.NamedTemporaryFile(delete=False) as fout:
for line in fin:
fout.write(line[1:])
outname = fout.name
os.remove(filename)
os.rename(outname, filename)
这样做确实可以防止文件被覆盖一半,但它会留下一个空洞,你可能已经删除了原始文件,并将新文件留在一个临时位置,你必须去搜索它。你可以通过将文件放在更容易找到的地方来使这个过程变得更加优雅(查看
NamedTemporaryFile
文档以了解如何实现)。或者将原始文件重命名为一个临时的名称,然后写入原始文件名,最后删除原始文件。还有其他各种可能性。但是要想在其他平台上获得相同的行为非常困难。
sed -i 's/^.//' filename.txt
。 - Robᵩ