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

时间:2013-09-20 19:51:44

标签: 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 lines:
    f.write(line[1:])
f.close()

6 个答案:

答案 0 :(得分:6)

您的代码已经 删除第一个字符。我将您的代码完全保存为dupy.pydupy.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,您可以使代码更简单,更健壮,更高效:< / p>

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文档以了解如何)。或者将原始文件重命名为临时名称,然后写入原始文件名,然后删除原始文件。或其他各种可能性。但要真正获得与其他平台相同的行为是非常困难的。

答案 1 :(得分:3)

您可以读取内存中的所有行,然后重新创建文件,

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)

答案 2 :(得分:3)

最基本的问题是,在将完整的内容读入数组seek之后,您需要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)

更好,在执行此类操作时,将更改写入 new 文件,然后在完成后将其重命名为旧文件。这导致更新发生&#34;原子地&#34; - 并发读者可以看到旧文件或新文件,而不是两者的错误组合。看起来像这样:

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.remove旧名称。不幸的是,这意味着有一个简短的窗口(没有双关语)并发读者会发现该文件不存在。据我所知,没有办法避免这种情况。)

答案 3 :(得分:2)

import re

with open(filename,'r+') as f:
    modified = re.sub('^.','',f.read(),flags=re.MULTILINE)
    f.seek(0,0)
    f.write(modified)

在正则表达式中:
^表示'字符串的开头' 带有标记^的{​​{1}}表示“行首”

re.MULTILINE表示“行开头唯一的一个字符”

一行的开头是字符串的开头或换行符之后的任何位置(换行符为^.
因此,我们可能会担心\n等序列中的某些换行符可能与正则表达式模式匹配 但点代表任何字符,除了换行符,然后所有换行符都与此正则表达式模式不匹配。

在读取由\n\n\n\n\n\n\n触发的文件期间,文件的指针一直持续到文件的末尾。

f.read()将文件的指针移回文件的开头

f.seek(0,0)在写入停止的位置放置一个新的EOF =文件结尾。因为修改后的文本比原始文本短,所以这是必要的 比较它与不带此行的代码的作用

答案 4 :(得分:2)

老实说,我真的不确定嵌套with 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:])

答案 5 :(得分:0)

虽然似乎有一些关于最佳实践的讨论以及它是否会在Windows上运行,但是对Python不熟悉,我能够运行第一个有效的示例并使其在我的Win环境中运行,该环境具有cygwin我的环境变量中的二进制文件路径并删除前3个字符(这是样本文件中的行号):

import os
from sys import argv

run, filename = argv

fin = open(filename)
fout = open(filename + '.tmp', 'w')
lines = fin.readlines()
for line in lines:
    fout.write(line[3:])
fout.close()
fin.close()

我选择不自动覆盖,因为我希望能够注意输出。

python c:\bin\remove1st3.py sampleCode.txt