You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析非固定分隔符Fortran输出文件为指定4维矩阵的方法

Fortran无分隔符系数表读取方案

核心问题出在按空格split的思路完全依赖分隔符规范,而这类老Fortran程序的输出为了对齐字段经常会省略负数前的空格,直接按字符位置写数,所以必须换不依赖分隔符的提取逻辑。

核心思路

  • 放弃按行读取、按空格分割的处理方式,直接对全量文本做模式匹配提取数值,完全绕开分隔符不固定的问题。
  • Fortran输出的科学计数法格式非常固定:[正负号]数字.数字E[正负号]数字,用正则[+-]?\d+\.\d+E[+-]\d+可以精准识别每一个数值,哪怕两个数粘在一起(比如2.452E-07-8.040E-07),也能正确切分成两个独立值,不会把第二个数的负号当成前一个数的一部分。
  • 按固定层级切分文本,逐段提取后组装成目标维度的矩阵:
    • 第一层:匹配所有带CLIMATOLOGY :的表头,把全文件切成4段对应4张系数表
    • 第二层:在每张表内匹配固定的3位月份缩写(JAN到DEC),切分12个月份块
    • 第三层:在每个月份块内匹配-85到85的纬度标识,切分18个纬度条目
    • 第四层:每个纬度条目内用正则提取25个数值,转成浮点型存入矩阵对应位置

参考实现代码

import re
import numpy as np

# 固定配置项
TABLE_NUM = 4
MONTH_NUM = 12
LAT_NUM = 18
LEVEL_NUM = 25
LAT_VALUES = [-85, -75, -65, -55, -45, -35, -25, -15, -5, 5, 15, 25, 35, 45, 55, 65, 75, 85]
MONTH_VALUES = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]

# 预编译正则提升效率
NUM_PATTERN = re.compile(r'[+-]?\d+\.\d+E[+-]\d+')
TABLE_HEAD_PATTERN = re.compile(r'.*CLIMATOLOGY :.*')
ENTRY_HEAD_PATTERN = re.compile(r'(' + '|'.join(MONTH_VALUES) + r')\s+(-?\d+)\s+\S+\s+cli\s+')

# 读入完整文件
with open("你的输入文件路径", "r", encoding="utf-8") as f:
    full_content = f.read()

# 初始化目标4维矩阵
TAB = np.zeros((TABLE_NUM, MONTH_NUM, LAT_NUM, LEVEL_NUM), dtype=np.float64)

# 逐表处理
table_pos = list(TABLE_HEAD_PATTERN.finditer(full_content))
for t_idx in range(TABLE_NUM):
    t_start = table_pos[t_idx].end()
    t_end = table_pos[t_idx+1].start() if t_idx < TABLE_NUM -1 else len(full_content)
    t_content = full_content[t_start:t_end]

    # 逐纬度条目处理
    entry_pos = list(ENTRY_HEAD_PATTERN.finditer(t_content))
    for e_idx, entry in enumerate(entry_pos):
        month_abbr, lat_val = entry.groups()
        m_idx = MONTH_VALUES.index(month_abbr)
        lat_idx = LAT_VALUES.index(int(lat_val))

        e_start = entry.end()
        e_end = entry_pos[e_idx+1].start() if e_idx < len(entry_pos)-1 else len(t_content)
        e_content = t_content[e_start:e_end]

        # 提取数值并做数量校验
        values = [float(v) for v in NUM_PATTERN.findall(e_content)]
        if len(values) != LEVEL_NUM:
            raise ValueError(f"表{t_idx} {month_abbr} 纬度{lat_val} 提取数值异常,预期{LEVEL_NUM}个,实际{len(values)}个")
        TAB[t_idx, m_idx, lat_idx, :] = values

补充说明

  • 这套逻辑完全不关心换行、空格的位置,只要数值本身是标准Fortran科学计数法格式,哪怕多个数完全粘连也能正确拆分,适配样例里的负号粘连场景。
  • 代码里加了数值长度校验,如果某段提取的数值数量不对会直接抛出异常标注位置,方便排查文件里的特殊格式问题。如果文件里存在小写e表示指数、或者整数格式的数值,只要微调NUM_PATTERN的匹配规则即可,核心处理逻辑不需要改动。

内容的提问来源于stack exchange,提问作者KuKaKi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 02:18:19