更新特定位置的文本文件中的字符串

时间:2012-05-22 23:23:06

标签: python string text io

我想找到一个更好的解决方案来实现以下三个步骤:

  1. 读取给定行的字符串
  2. 更新字符串
  3. 写回更新后的字符串
  4. 下面是我的代码,但我想知道有更好的(简单)解决方案吗?

    new='99999'
    
    f=open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP','r+')
    lines=f.readlines()
    #the row number we want to update is given, so just load the content
    x = lines[95]
    print(x)
    f.close()
    
    
    #replace
    f1=open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP')
    con = f1.read()
    print con
    con1 = con.replace(x[2:8],new) #only certain columns in this row needs to be updated
    print con1
    f1.close()
    
    
    #write
    f2 = open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP', 'w')
    f2.write(con1)
    f2.close()
    

    谢谢! 更新:这次从jtmoulia得到一个想法变得更容易

    def replace_line(file_name, line_num, col_s, col_e, text):
        lines = open(file_name, 'r').readlines()
        temp=lines[line_num]
        temp = temp.replace(temp[col_s:col_e],text)
        lines[line_num]=temp
        out = open(file_name, 'w')
        out.writelines(lines)
        out.close()
    

4 个答案:

答案 0 :(得分:3)

文本数据的问题,即使列表,也是字节偏移是不可预测的。例如,当用字符串表示数字时,每个数字有一个字节,而当使用二进制(例如二进制补码)时,对于小整数和大整数,总是需要四个或八个字节。

尽管如此,如果您的文本格式足够严格,您可以通过替换字节而不改变文件大小来实现,您可以尝试使用standard mmap module。有了它,您将能够将文件视为可变字节字符串,并在其中修改部分内容并让内核为您保存文件。

否则,其他任何答案都更适合这个问题。

答案 1 :(得分:1)

嗯,首先,您不需要每次都重新打开并从文件中读取。 r+模式允许您读取和写入给定文件。

也许像

with open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP', 'r+') as f:
    lines = f.readlines()
    #... Perform whatever replacement you'd like on lines
    f.seek(0)
    f.writelines(lines)

此外,Editing specific line in text file in python

答案 2 :(得分:0)

当我必须做类似的事情(对于Webmin定制)时,我完全用PERL完成它,因为这是Webmin框架使用的,我发现它很容易。我假设(但不确定)Python中有相同的东西。首先将整个文件一次性读入内存(执行此操作的PERL方式可能称为“slurp”)。 (这种将整个文件保存在内存中的想法,而不仅仅是一行用来做一点意义{甚至不可能}。但是现在RAM太大了,这是唯一的方法。)然后使用split运算符将文件分成行并将每行放在巨型数组的不同元素中。然后,您可以使用所需的行号作为数组的索引(记住数组索引通常以0开头)。最后,使用“正则表达式”处理来更改行的文本。然后更改另一行,另一行,另一行(或对同一行进行另一次更改)。完成所有操作后,使用join将数组中的所有行重新组合成一个巨大的字符串。然后写出整个修改过的文件。

虽然我没有完整的代码,但这里有一些PERL代码的近似片段,所以你可以看到我的意思:

our @filelines = ();
our $lineno = 43;
our $oldstring = 'foobar';
our $newstring = 'fee fie fo fum';
$filelines[$lineno-1] =~ s/$oldstring/$newstring/ig; 
# "ig" modifiers for case-insensitivity and possible multiple occurences in the line
# use different modifiers at the end of the s/// construct as needed

答案 3 :(得分:-1)

FILENAME = 'C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP'
lines = list(open(FILENAME))
lines[95][2:8] = '99999'
open(FILENAME, 'w').write(''.join(lines))