Python 删除文本文件中每行的第一个字符
我是Python新手,一般来说是编程新手 我想删除文本文件中每一行的第一个字符,并将更改写回该文件。例如,我有一个36行的文件,每行的第一个字符包含一个符号或数字,我希望将其删除 我在这里做了一点代码,但它并没有像预期的那样工作,它只复制了整个留置权。任何帮助都将提前感谢Python 删除文本文件中每行的第一个字符,python,python-2.7,Python,Python 2.7,我是Python新手,一般来说是编程新手 我想删除文本文件中每一行的第一个字符,并将更改写回该文件。例如,我有一个36行的文件,每行的第一个字符包含一个符号或数字,我希望将其删除 我在这里做了一点代码,但它并没有像预期的那样工作,它只复制了整个留置权。任何帮助都将提前感谢 from sys import argv run, filename = argv f = open(filename, 'a+') f.seek(0) lines = f.readlines() for line in
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()
您的代码已经删除了第一个字符。我将您的代码准确地保存为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,我可以解释如何执行此操作。)
通过将
与
语句一起使用,直接在文件上循环而不是调用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上实现这种“write temp and rename”算法。但你只需要做一点额外的工作就可以接近目标: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)
这确实可以防止您将文件覆盖一半,但会留下一个漏洞,您可能已经删除了原始文件,并将新文件保留在一个临时位置,您必须搜索该位置。您可以通过将文件放在更容易找到的地方(请参阅文档了解如何查找)使这一点变得更好。或者将原始文件重命名为临时名称,然后写入原始文件名,然后删除原始文件。或者其他各种可能性。但要真正获得与其他平台上相同的行为是非常困难的。您可以读取内存中的所有行,然后重新创建文件
from sys import argv
run, filename = argv
with open(filename, 'r') as f:
data = [i[1:] for i in f
with open(filename, 'w') as f:
f.writelines(i+'\n' for i in data) # this is for linux. for win use \r\n
或者您可以创建其他文件,并将数据逐行从第一个文件移动到第二个文件。然后,如果您愿意,可以重命名它
from sys import argv
run, filename = argv
new_name = filename + '.tmp'
with open(filename, 'r') as f_in, open(new_name, 'w') as f_out:
for line in f_in:
f_out.write(line[1:])
os.rename(new_name, filename)
最基本的问题是,在将文件的完整内容读入数组
f
后,需要查找
回到文件的开头。由于要缩短文件,因此还需要使用truncate
在完成后调整文件的正式长度。此外,打开模式a+
(a表示追加)会覆盖seek
,并强制所有写入操作转到文件的末尾。因此,您的代码应该如下所示:
import sys
def main(argv):
filename = argv[1]
with open(filename, 'r+') as f:
lines = f.readlines()
f.seek(0)
for line in lines:
f.write(line[1:])
f.truncate()
if __name__ == '__main__': main(sys.argv)
import os
import sys
import tempfile
def main(argv):
filename = argv[1]
with open(filename, 'r') as inf:
with tempfile.NamedTemporaryFile(dir=".", delete=False) as outf:
tname = outf.name
for line in inf:
outf.write(line[1:])
os.rename(tname, filename)
if __name__ == '__main__': main(sys.argv)
在执行类似操作时,最好将更改写入新文件,然后在完成后将其重命名为旧文件。这导致更新以“原子方式”进行——并发读卡器看到的是旧文件或新文件,而不是两者的某个损坏组合。看起来是这样的:
import sys
def main(argv):
filename = argv[1]
with open(filename, 'r+') as f:
lines = f.readlines()
f.seek(0)
for line in lines:
f.write(line[1:])
f.truncate()
if __name__ == '__main__': main(sys.argv)
import os
import sys
import tempfile
def main(argv):
filename = argv[1]
with open(filename, 'r') as inf:
with tempfile.NamedTemporaryFile(dir=".", delete=False) as outf:
tname = outf.name
for line in inf:
outf.write(line[1:])
os.rename(tname, filename)
if __name__ == '__main__': main(sys.argv)
(注意:通过rename
自动替换文件在Windows上不起作用;您必须os。首先删除
旧名称。不幸的是,这意味着有一个简短的窗口(没有双关语),并发读卡器会发现文件不存在。据我所知,无法避免此情况。)
在正则表达式模式中:^
表示“字符串开头”^
带有标志re.多行
表示“行的开始”
^。
表示“行首只有一个字符”
行的开头是字符串的开头或换行后的任何位置(换行是\n
)因此,我们可能担心序列中的某些换行符,如
\n\n\n\n\n
可能与regex模式匹配。但是点代表除换行符以外的任何字符,那么所有的换行符都与这个正则表达式模式不匹配 在由
f.read()
触发的文件读取过程中,文件指针一直指向文件末尾
f.seek(0,0)
将文件指针移回文件的开头
f.truncate()
将新的EOF=文件结尾放在写入停止的位置。这是必要的,因为修改后的文本比原始文本短。比较一下没有这一行的代码,我真的不知道用open()嵌套
有多好/有多坏,但是你可以这样做
with open(filename_you_reading_lines_FROM, 'r') as f0:
with open(filename_you_appending_modified_lines_TO, 'a') as f1:
for line in f0:
f1.write(line[1:])
虽然似乎有一些关于最佳实践以及它是否会在Windows上运行的讨论,但作为Python新手,我能够运行第一个有效的示例,并使其在Win环境中运行,该环境变量路径中包含cygwin二进制文件,并删除了前3个字符(这些是示例文件中的行号):
我选择不自动覆盖,因为我希望能够查看输出
python c:\bin\remove1st3.py sampleCode.txt
你的上一个版本在Windows上不起作用。举个例子来说,这很好,特别是如果OP不在Windows上,但是你应该提到它。我会试试这个,我喜欢这个想法。你的目标是编写程序或删除字符吗?如果是后者,那么就这样做:sed-I's/^./'filename.txt
。只需删除字符。顺便说一句,这是reg-exp吗?我如何使用你的code行?要使用Rob的解决方案,您需要有sed
软件installed@skzd-假设您正在运行Unix或Li