1

到目前为止,我有一个 python 脚本,大部分是为我目前正在从事的项目编写的,并且遇到了障碍。我基本上运行了一个程序,它会输出以下输出文件(称为 big.dmp):

)O+_05 Big-body initial data  (WARNING: Do not delete this line!!)
) Lines beginning with `)' are ignored.
)---------------------------------------------------------------------
  style (Cartesian, Asteroidal, Cometary) = Cartesian
  epoch (in days) =    1365250.
)---------------------------------------------------------------------
COMPSTAR r=5.00000E-01 d=3.00000E+00  m= 0.160000000000000E+01
  4.570923967127310E-01  1.841433531828977E+01  0.000000000000000E+00
 -6.207379670518027E-03  1.540861575481520E-04  0.000000000000000E+00
  0.000000000000000E+00  0.000000000000000E+00  0.000000000000000E+00

现在有了这个文件,我需要编辑 epoch 行和以 COMPSTAR 开头的行,同时保持从积分到积分的其余信息不变,因为最后 3 行包含我的对象的笛卡尔坐标,本质上是程序输出的内容.

我知道如何使用f = open('big.dmp', 'w')f.write('text here')创建初始文件,但是如何将最后三行读入新的 big.dmp 文件以进行下一次集成?

4

4 回答 4

1

如果您的文件格式在行号方面是固定的,则此解决方案将仅更改两行:

with open('big.dmp') as inf, open('out.txt', 'w') as outf:
    data = inf.readlines()
    data[4] = '  epoch (in days) = 9999.\n'      # line with epoch
    data[6] = 'COMPSTAR r=2201 d=3330  m= 12\n'  # line with COMPSTAR
    outf.writelines(data)

产生这个输出文件:

)O+_05 Big-body initial data  (WARNING: Do not delete this line!!)
) Lines beginning with `)' are ignored.
)---------------------------------------------------------------------
  style (Cartesian, Asteroidal, Cometary) = Cartesian
  epoch (in days) = 9999.
)---------------------------------------------------------------------
COMPSTAR r=2201 d=3330  m= 12
  4.570923967127310E-01  1.841433531828977E+01  0.000000000000000E+00
 -6.207379670518027E-03  1.540861575481520E-04  0.000000000000000E+00
  0.000000000000000E+00  0.000000000000000E+00  0.000000000000000E+00

显然,如果行号不一致,这将不起作用,但我想我会提供它,以防您的数据格式在行号方面是一致的

此外,由于它一次将整个文件读入内存,因此对于真正的大文件来说,它不是一个理想的解决方案。

使用打开文件的优点with是,当您完成文件或遇到异常时,它们会自动为您关闭。

有更灵活的解决方案(搜索字符串,逐行处理文件),但如果您的数据是固定的且很小,那么利用这些因素没有不利之处。聪明的人曾经说过“简单胜于复杂”。(Python之禅)

于 2012-06-29T22:25:15.190 回答
1

大概是这样的?

infile = open('big1.dmp')
outfile = open('big2.dmp', 'w')

for line in infile:
    if line.startswith(')'):
        # ignore comments
        pass
    elif 'epoch' in line:
        # do something with line
        line = line.replace('epoch', 'EPOCH')
    elif line.startswith('COMPSTAR'):
        # do something with line
        line = line.replace('COMPSTAR', 'comparison star')
    outfile.write(line)
于 2012-06-29T22:15:46.540 回答
1

这是一个更容变化的版本:

import re

reg_num = r'\d+'
reg_sci = r'[-+]?\d*\.?\d+([eE][+-]?\d+)?'

def update_config(s, finds=None, replaces=None, **kwargs):
    if finds is None:    finds = update_config.finds
    if replaces is None: replaces = update_config.replaces

    for name,value in kwargs.iteritems():
        s = re.sub(finds[name], replaces[name].format(value), s)
    return s

update_config.finds = {
    'epoch': r'epoch \(in days\) =\s*'+reg_num+'\.',
    'r':     r' r\s*=\s*' + reg_sci,
    'd':     r' d\s*=\s*' + reg_sci,
    'm':     r' m\s*=\s*' + reg_sci
}
update_config.replaces = {
    'epoch': 'epoch (in days) ={:>11d}.',
    'r':     ' r={:1.5E}',
    'd':     ' d={:1.5E}',
    'm':     ' m= {:1.15E}'
}

def main():
    with open('big.dmp') as inf:
        s = inf.read()

    s = update_config(s, epoch=1365252, r=0.51, d=2.99, m=1.1)

    with open('big.dmp', 'w') as outf:
        outf.write(s)

if __name__=="__main__":
    main()
于 2012-06-30T00:04:13.540 回答
0

有点难以理解您想要什么,但假设您只想删除不以 ) 开头的行:

text = open(filename).read()
lines = text.split("\n")
result = [line for line in lines if not line.startswith(")")

或者,一个班轮:

[line for line in open(file_name).read().split("\n") if not line.startswith(")")]
于 2012-06-29T22:11:17.593 回答