Python 删除文本文件中每行的第一个字符

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

我是Python新手,一般来说是编程新手

我想删除文本文件中每一行的第一个字符,并将更改写回该文件。例如,我有一个36行的文件,每行的第一个字符包含一个符号或数字,我希望将其删除

我在这里做了一点代码,但它并没有像预期的那样工作,它只复制了整个留置权。任何帮助都将提前感谢

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