要在file-python中替换的行集

要在file-python中替换的行集,python,replace,updates,lines,Python,Replace,Updates,Lines,我是python新手。我试图使用一个包含新数据的文件(newprops)来替换第二个文件中的旧数据。两个文件都超过3MB 包含新数据的文件如下所示: PROD 850 30003 0.096043 PROD 851 30003 0.096043 PROD 853 30003 0.096043 PROD 852 30003 0.096043 .... 包含旧数据的原始文件类似于: CROD 850 123456 123457

我是python新手。我试图使用一个包含新数据的文件(newprops)来替换第二个文件中的旧数据。两个文件都超过3MB

包含新数据的文件如下所示:

PROD    850 30003   0.096043  
PROD    851 30003   0.096043  
PROD    853 30003   0.096043  
PROD    852 30003   0.096043  
....
包含旧数据的原始文件类似于:

CROD    850     123456 123457 123458 123459  
PROD    850     30003   0.08  
CROD    851     123456 123457 123458 123459  
PROD    851     30003   0.07  
CROD    852     123456 123457 123458 123459  
PROD    852     30003   0.095  
CROD    853     123456 123457 123458 123459  
PROD    853     30003   0.095  
....
输出应为:

CROD    850     123456 123457 123458 123459  
PROD    850     30003   0.096043  
CROD    851     123456 123457 123458 123459  
PROD    851     30003   0.096043  
CROD    852     123456 123457 123458 123459  
PROD    852     30003   0.096043  
CROD    853     123456 123457 123458 123459  
PROD    853     30003   0.096043  
以下是我目前掌握的情况:

import fileinput

def prop_update(newprops,bdffile):

    fnewprops=open(newprops,'r')
    fbdf=open(bdffile,'r+')
    newpropsline=fnewprops.readline()
    fbdfline=fbdf.readline()


    while len(newpropsline)>0:
        fbdf.seek(0)
        propname=newpropsline.split()[1]
        propID=newpropsline.split()[2]
            while len(fbdfline)>0:
                if propID and propname in fbdfline:
                    bdffile.write(newpropsline) #i'm stuck here... I want to delete the old line and use updated value                   
                else:                    
                    fbdfline=fbdfline.readline()

        newpropsline=fnewprops.readline()

    fnewprops.close()

请帮忙

假设新行长度等于原始行长度的一半,您可以从原始行中取出第二行,用新行压缩,然后重新打开原始行并写入更新的行:

from itertools import izip

with open("new.txt") as f,open("orig.txt") as f2:
    lines = f2.readlines()
    zipped = izip(lines[::2],f) # just use zip for python3
    with open("orig.txt","w") as out:
        for pair in zipped:
            out.writelines(pair)
如果希望根据第二列对行进行排序,还需要手动剥离并插入换行符,以便将最后的行分隔开:

from itertools import izip,islice

with open("new.txt") as f, open("orig.txt") as f2:
    orig = sorted((x.strip() for x in islice(f2, 0, None, 2)), key=lambda x: int(x.split(None, 2)[1]))
    new = sorted((x.strip() for x in f), key=lambda x:int(x.split(None,2)[1]))
    zipped = izip(orig, new)
    with open("orig.txt","w") as out:
        for pair in zipped:
            out.write("{}\n{}\n".format(*pair))
输出:

CROD 850 123456 123457 123458 123459
PROD 850 30003 0.096043
CROD 851 123456 123457 123458 123459
PROD 851 30003 0.096043
CROD 852 123456 123457 123458 123459
PROD 852 30003 0.096043
CROD 853 123456 123457 123458 123459
PROD 853 30003 0.096043
如果长度不相同,您可以将fillvalue设置为
”,这样就不会丢失任何数据:


如果旧文件已按顺序排列,只需忘记f2上的排序调用,并使用
f2.readlines()[::2]
,但如果不按顺序排列,则这将确保所有行都基于第二列排序,而不考虑原始顺序。

您可以使用dict为新数据编制索引。然后将原始文件逐行写入新文件,并在运行时更新索引中的数据。看起来前三项应该是键(“PROD 850 30003”),可以使用正则表达式(如
(PROD\s+\d+\s+\d+
)将其取出


如果您让我们知道哪一块数据是
newprops
以及哪一块数据是
bdffile
,这将有助于更好地帮助您。newprops是顶部的块,bdffile是第二个执行项。非常感谢。这确实假设行的顺序正确,并且没有丢失数字。。。从提供的数据来看,似乎853可能出现在852…@aychedee之前,如果是这种情况,则必须按第二个字对行进行排序,这不难通过构建自定义生成器来限制内存消耗。如果
orig.txt
太大,这可能会让人害怕:)@AdamSmith,没错,但OP的FIE不是很大,内存不会成为问题,所以没有可怕的时刻。:)OP说现在大约有3MB,对itertools不熟悉,很有帮助。原始版本在exerpt的顶部和底部还包含许多其他数据值,可能在文件中的任何位置,因此获取第二行不一定是真的(如果您熟悉它,它是一个nastran bdf文件)。太棒了,这正是我需要的!感谢您的帮助和代码中的外行解释:)
import re
_split_new = re.compile(r"(PROD\s+\d+\s+\d+)(.*)")

# create an index for the PROD items to be updated

# this might be a bit more understandable...
#with open('updates.txt') as updates:
#    new_data = {}
#    for line in updates:
#        match = _split_new.match(line)
#        if match:
#            key, value = match.groups()
#            new_data[key] = value

# ... but this is fancier (and likely faster)
with open('updates.txt') as updates:
    new_data = dict(match.groups() 
        for match in (_split_new.search(line) for line in updates)
        if match)

# then process the updates
with open('origstuff.txt') as orig, open('newstuff.txt', 'w') as newstuff:
    # for each line in the original...
    for line in orig:
        match = _split_new.match(line)
        # ... see if its a PROD line
        if match:
            key, value = match.groups()
            # ... and rewrite with value from indexing dict (defaulting to current value)
            newstuff.write("%s%s\n" % (key, new_data.get(key, value)))
        else:
            # ... or just the original line
            newstuff.write(line)