在Python中逐块读取,切片和重新构造数据文件

时间:2012-06-05 15:59:45

标签: python text format block

Fortran程序生成的文本文件包含需要重新格式化的“块”数据(Python脚本)。

此文件中的每个“块”数据对应于块开头指定的“时间:”。所有“块”都具有固定的大小和结构。

我需要从“Head”和“Moisture”列中提取对应于每个“Time:”的不同“Depths”(0,-1和-2)的数据。

注意:开头的标题不是重复“数据块”的一部分。

示例输入文件:

 ******* Program Simulation
 ******* 
 This is initial header information for Simulation                              
 Date:   1. 6.    Time:  15: 3:39
 Units: L = cm   , T = min  , M = mmol 

 Time:        0.0000

 Node      Depth      Head Moisture       K         
           [L]        [L]    [-]        [L/T]      

   1     0.0000     -37.743 0.0630   0.5090E-05  
   2    -1.0000     -36.123 0.0750   0.5090E-05  
   3    -2.0000     -33.002 0.0830   0.5090E-05  
end

 Time:      360.0000

 Node      Depth      Head Moisture       K         
           [L]        [L]    [-]        [L/T]     

   1     0.0000 -0.1000E+07 0.0450   0.1941E-32  
   2    -1.0000    -253.971 0.0457   0.4376E-10  
   3    -2.0000     -64.510 0.0525   0.2264E-06  
end

 Time:      720.0000

 Node      Depth      Head Moisture       K         
           [L]        [L]    [-]        [L/T]     

   1     0.0000 -0.1000E+07 0.0550   0.1941E-32  
   2    -1.0000    -282.591 0.0456   0.2613E-10 
   3    -2.0000     -71.829 0.0513   0.1229E-06  
end

期望的输出

Time        Head(Depth=0)   Head(Depth=-1)  Head(Depth=-2)  Moisture(Depth=0)   Moisture(Depth=-1)  Moisture(Depth=-2)
0.0000      -37.743         -36.123         -33.002         0.0630              0.0750              0.0830
360.0000    -0.1000E+07     -253.971        -64.510         0.0450              0.0457              0.0525
720.0000    -0.1000E+07     -282.591        -71.829         0.0550              0.0456              0.0513

我如何从每个“Time:”到“end”关键字逐块读取输入文件并重新格式化为所需的输出?

3 个答案:

答案 0 :(得分:1)

这是解析部分:

import re

data = []

with open(xxxx) as f:
    for line in f:
        m = re.match(r'^\s+Time:\s+([\d.]+)', line)
        if m:
            data.append([float(m.group(1))])
        elif re.match(r'^\s+\d+', line):
            data[-1].append(map(float, line.strip().split()))

产生

[[0.0,
  [1.0, 0.0, -37.743, 0.063, 5.09e-06],
  [2.0, -1.0, -36.123, 0.075, 5.09e-06],
  [3.0, -2.0, -33.002, 0.083, 5.09e-06]],
 [360.0,
  [1.0, 0.0, -1000000.0, 0.045, 1.941e-33],
  [2.0, -1.0, -253.971, 0.0457, 4.376e-11],
  [3.0, -2.0, -64.51, 0.0525, 2.264e-07]],
 [720.0,
  [1.0, 0.0, -1000000.0, 0.055, 1.941e-33],
  [2.0, -1.0, -282.591, 0.0456, 2.613e-11],
  [3.0, -2.0, -71.829, 0.0513, 1.229e-07]]]

从中打印所需的表格应该很容易。

答案 1 :(得分:1)

修改:我做了一些更改,因此实际运行

from itertools import chain

def get_lines(f, n=1):
    return [f.next() for i in xrange(n)]

class BlockReader(object):
    def __init__(self, f, n=1):
        self.f = f
        self.n = n
    def __iter__(self):
        return self
    def next(self):
        return [self.f.next() for i in xrange(self.n)]

fmt = "{:<12}" + "{:<16}"*6 + "\n"
cols = [
    "Time",
    "Head(Depth=0)",
    "Head(Depth=-1)",
    "Head(Depth=-2)",
    "Moisture(Depth=0)",
    "Moisture(Depth=-1)",
    "Moisture(Depth=-2)"
]

def main():
    with open("simulation.txt") as inf, open("result.txt","w") as outf:
        # throw away input header
        get_lines(inf, 5)
        # write output header
        outf.write(fmt.format(*cols))

        # read input file in ten-line chunks
        for block in BlockReader(inf, 10):
            # grab time value
            time = float(block[1].split()[1])

            # grab head and moisture columns
            data = (line.split()[2:4] for line in block[6:9])
            values = (map(float,dat) for dat in data)
            h,m = zip(*values)

            # write data to output file
            outf.write(fmt.format(*chain([time],h,m)))

if __name__=="__main__":
    main()

输出

Time        Head(Depth=0)   Head(Depth=-1)  Head(Depth=-2)  Moisture(Depth=0)Moisture(Depth=-1)Moisture(Depth=-2)
0.0         -37.743         -36.123         -33.002         0.063           0.075           0.083           
360.0       -1000000.0      -253.971        -64.51          0.045           0.0457          0.0525          
720.0       -1000000.0      -282.591        -71.829         0.055           0.0456          0.0513          

答案 2 :(得分:0)

如果文件不是太大,你可以这样做:

f = open('somefile')
file = f.read()
blocks = file.split('Time:')[1:]