我需要从文件中提取某些数据,但是该文件的格式设置为可供人类读取,因此是不规则的。首先,在任何数据实际开始之前,会有大量文本:


   DL_POLY Version 2.20

                        Running on   10 nodes

  
  
    
    
    
    
    
    
    *************** DLPOLY:LiNbO3> ***************
    
    
    
    
    
    
  
  
  模拟控制参数
  
  模拟温度1.4500E + 03
  
  模拟压力(katm)0.0000E + 00
  
  选定的时间步数8000
  
  平衡期500
  
  数据打印间隔80
  
  统计文件间隔80
  
  模拟时间步5.0000E-04
  
  鼻胡佛(Melchionna)各向同性N-P-T
  恒温器松弛时间1.0000E-01
  稳压器松弛时间5.0000E-01
  
  轨迹文件选项开启
  轨迹文件开始1
  轨迹文件间隔80
  轨迹文件信息键2
  ...


稍后会得到实际数据,但格式很有趣:


  
  
  步骤eng_tot temp_tot eng_cfg eng_vdw eng_cou eng_bnd> eng_ang eng_dih eng_tet
  时间(ps)eng_pv temp_rot vir_cfg vir_vdw vir_cou vir_bnd> vir_ang vir_con vir_tet
  cpu(s)体积temp_shl eng_shl vir_shl alpha beta> gamma vir_pmf按
  
  
    
    
    1 -1.1289E + 05 1.4750E + 03 -1.1386E + 05 1.7276E + 04 -1.3114E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
         0.0 -1.1545E + 05 0.0000E + 00 9.6539E + 03 -1.2118E + 05 1.3083E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
         0.8 5.3733E + 04 1.2367E + 02 0.0000E + 00 0.0000E + 00 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -7.5549E + 01
  
  
  轧制-1.1289E + 05 1.4750E + 03 -1.1386E + 05 1.7276E + 04 -1.3114E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
  平均值-1.1545E + 05 0.0000E + 00 9.6539E + 03 -1.2118E + 05 1.3083E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
            5.3733E + 04 1.2367E + 02 0.0000E + 00 0.0000E + 00 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -7.5549E + 01
  
  
    
    
    80 -1.1290E + 05 1.5021E + 03 -1.1392E + 05 2.1894E + 04 -1.3726E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
         0.0 -1.1256E + 05 0.0000E + 00 8.6671E + 02 -1.3974E + 05 1.3707E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
        10.6 5.3149E + 04 1.1377E + 03 1.4419E + 03 3.5382E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 1.1119E + 01
  
  
  轧制-1.1290E + 05 1.6145E + 03 -1.1398E + 05 2.0750E + 04 -1.3588E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
  平均值-1.1333E + 05 0.0000E + 00 3.3694E + 03 -1.3512E + 05 1.3565E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
            5.3481E + 04 1.0997E + 03 1.1430E + 03 2.8391E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -1.2096E + 01
  
  
    
    
    160 -1.1287E + 05 1.2629E + 03 -1.1376E + 05 2.1450E + 04 -1.3633E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
         0.1 -1.1249E + 05 0.0000E + 00 3.8761E + 02 -1.3824E + 05 1.3612E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
        20.5 5.3375E + 04 4.9015E + 02 1.1243E + 03 2.5052E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 1.2676E + 01
  
  
  轧制-1.1288E + 05 1.4677E + 03 -1.1389E + 05 2.1589E + 04 -1.3663E + 05 0.0000E + 00 0.0000E + 00 0.0000E + 00 0.0000E + 00
  平均值-1.1235E + 05 0.0000E + 00 2.1147E + 02 -1.3884E + 05 1.3643E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
            5.3152E + 04 7.4818E + 02 1.1440E + 03 2.6211E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 1.7174E + 01
  
  
    
  


在第9个数据间隔上,有一个轻微的异常现象:


  
    
  
  
  在步骤500关闭温度标度
  
  
    

 560 -1.1287E+05  1.4709E+03 -1.1390E+05  2.1600E+04 -1.3678E+05  0.0000E+00  >0.0000E+00  0.0000E+00  0.0000E+00
 0.3 -1.1292E+05  0.0000E+00  1.9253E+03 -1.3743E+05  1.3656E+05  0.0000E+00  >0.0000E+00  0.0000E+00  0.0000E+00
68.4  5.4300E+04  1.5043E+02  1.2775E+03  2.7947E+03  5.6396E+01  5.6396E+01  >5.6396E+01  0.0000E+00  2.0576E-01

  
  
  轧制-1.1286E + 05 1.4784E + 03 -1.1390E + 05 2.1546E + 04 -1.3673E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
  平均值-1.1298E + 05 0.0000E + 00 2.1361E + 03 -1.3717E + 05 1.3651E + 05 0.0000E + 00> 0.0000E + 00 0.0000E + 00 0.0000E + 00
            5.4303E + 04 2.2261E + 02 1.2785E + 03 2.8027E + 03 5.6396E + 01 5.6396E + 01> 5.6396E + 01 0.0000E + 00 -1.7421E + 00
  
  
    
  
  
  


如您所见,有一对“ ----”行可能会干扰数据的正确解析。

可以说我只想从该文件中获取“ eng_tot”数据(粗体数字),我将如何在Python中做到这一点?该数字始终在文件中的同一位置(第二个数量,第二组---- s之后的第一行。

顺便说一下,其中具有所有定义的标头部分每8步重复一次,执行第一步,其中有9行。我只想忽略第一步。现在,让我说我要从第295行开始。请注意,对于python和程序设计我还是很陌生,因此感谢您提供的所有帮助。

这是我尝试的代码,但是Eng_Total仍然是一个空集:

import re
import inspect

def lineno():
    """Returns the current line number"""
    linenum = inspect.currentframe().f_back.f_lineno
infile =  open('FilePath/OUTPUT.01').read()
Eng_Total = []
for line in infile:
#    if 'eng_tot' in line.split():
     if re.match("\s+-+\s+", line):
    lineno(line)
        line = linenum+1
        sanitized_line = line[8:]
        eng_total = line.split()[0]
        Eng_Total.append(eng_total)
print Eng_Total

最佳答案

我可能会这样做:


遍历输出中的行
搜索一个包含eng_tot的内容:


if 'eng_tot' in line.split(): process_blocks

逐行划线,直到所有破折号都匹配(在两侧都有可选的空格)


if re.match("\s+-+\s+", line): proccess_metrics_block

处理第一行指标:


切断第一列的内容(这使得它很难解析,因为它可能不存在)


sanitized_line = line[8:]
eng_total = line.split()[0],第一列现在为eng_total


跳过行,直到到达另一行破折号,然后重新开始


看到您的修改后:


您需要在文件顶部导入re(正则表达式)模块:import re
process_blocksprocess_metrics_block是伪代码。除非您定义它们,否则它们不存在。 :)您不需要这些功能,可以使用基本循环(while)和条件(if)语句来避免使用它们。
您必须确保您了解自己在做什么,而不仅仅是从堆栈溢出中复制! :)


看来您正在尝试做这样的事情。看来可行,但是我敢肯定,您可以花一些点时间做些更好的事情:

import re

def find_header(lines):
  for (i, line) in enumerate(lines):
    if 'eng_tot' in line.split():
      return i
  return None

def find_next_separator(lines, start):
  for (i, line) in enumerate(lines[start+1:]):
    if re.match("\s*-+\s*", line):
      return i + start + 1
  return None

if __name__ == '__main__':
  totals = []
  lines = open('so.txt').readlines()

  header = find_header(lines)
  start = find_next_separator(lines, header+1)

  while True:
    end = find_next_separator(lines, start+1)
    if end is None: break

    # Pull out block, after line of dashes.
    metrics_block = lines[start+1:end]

    # Pull out 2nd column from 1st line of metrics.
    eng_total = metrics_block[0].split()[1]
    totals.append(eng_total)

    start = end

  print totals


您可以使用一个生成器,使其更具Python性:

def metric_block_iter(lines):
  start = find_next_separator(lines, find_header(lines)+1)
  while True:
    end = find_next_separator(lines, start+1)
    if end is None: break
    yield (start, end)
    start = end


if __name__ == '__main__':
  totals = []
  lines = open('so.txt').readlines()

  for (start, end) in metric_block_iter(lines):
    # Pull out block, after line of dashes.
    metrics_block = lines[start+1:end]

    # Pull out 2nd column from 1st line of metrics.
    eng_total = metrics_block[0].split()[1]
    totals.append(eng_total)

  print totals

关于python - 如何从python中格式不规则的数据文件中提取数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3086257/

10-12 21:13