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

Python文件解析异常:仅执行首个解析函数?求多工具解决方案

问题需求与故障现象
  • 需求:从输入文件提取两类行的字段:
    1. 以MEMRANGE开头的行:提取BASEVALUE、INSTANCE、SLAVEBUSINTERFACE的值,按指定格式输出
    2. 以PORT开头的行:提取CLKFREQUENCY、SIGNAME的值输出
  • 故障:编写的Python代码中,两个解析函数单独测试均正常,但写入输出文件时仅第一个执行的函数有输出(当前输出仅包含PORT行结果,缺失MEMRANGE行内容),怀疑是文件访问操作有误
  • 接受其他实现方案:sed、awk或grep

输入文件示例

MEMRANGE BASEVALUE=0x10000000 INSTANCE=uart0 SLAVEBUSINTERFACE=apb
MEMRANGE BASEVALUE=0x20000000 INSTANCE=spi0 SLAVEBUSINTERFACE=ahb
PORT CLKFREQUENCY=100000000 SIGNAME=clk_cpu
PORT CLKFREQUENCY=50000000 SIGNAME=clk_periph

原Python代码

def parse_memrange(line):
    parts = line.split()
    base = [p.split('=')[1] for p in parts if p.startswith('BASEVALUE=')][0]
    instance = [p.split('=')[1] for p in parts if p.startswith('INSTANCE=')][0]
    slave = [p.split('=')[1] for p in parts if p.startswith('SLAVEBUSINTERFACE=')][0]
    return f"Memory: {instance} @ {base} (Bus: {slave})"

def parse_port(line):
    parts = line.split()
    clk = [p.split('=')[1] for p in parts if p.startswith('CLKFREQUENCY=')][0]
    sig = [p.split('=')[1] for p in parts if p.startswith('SIGNAME=')][0]
    return f"Port: {sig} - {clk} Hz"

with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    # 先处理PORT行
    for line in infile:
        line = line.strip()
        if line.startswith('PORT'):
            outfile.write(parse_port(line) + '\n')
    # 再处理MEMRANGE行
    for line in infile:
        line = line.strip()
        if line.startswith('MEMRANGE'):
            outfile.write(parse_memrange(line) + '\n')

当前输出(output.txt)

Port: clk_cpu - 100000000 Hz
Port: clk_periph - 50000000 Hz

期望输出

Memory: uart0 @ 0x10000000 (Bus: apb)
Memory: spi0 @ 0x20000000 (Bus: ahb)
Port: clk_cpu - 100000000 Hz
Port: clk_periph - 50000000 Hz

解决方案

Python代码修正

问题根源:第一次遍历文件后,文件指针已移动到文件末尾,第二次遍历无法读取任何内容。提供两种修复方式:

方法1:一次性读取所有行到列表

def parse_memrange(line):
    parts = line.split()
    base = [p.split('=')[1] for p in parts if p.startswith('BASEVALUE=')][0]
    instance = [p.split('=')[1] for p in parts if p.startswith('INSTANCE=')][0]
    slave = [p.split('=')[1] for p in parts if p.startswith('SLAVEBUSINTERFACE=')][0]
    return f"Memory: {instance} @ {base} (Bus: {slave})"

def parse_port(line):
    parts = line.split()
    clk = [p.split('=')[1] for p in parts if p.startswith('CLKFREQUENCY=')][0]
    sig = [p.split('=')[1] for p in parts if p.startswith('SIGNAME=')][0]
    return f"Port: {sig} - {clk} Hz"

with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    # 读取所有行到列表,避免指针偏移问题
    lines = infile.readlines()
    # 先处理MEMRANGE行
    for line in lines:
        line = line.strip()
        if line.startswith('MEMRANGE'):
            outfile.write(parse_memrange(line) + '\n')
    # 再处理PORT行
    for line in lines:
        line = line.strip()
        if line.startswith('PORT'):
            outfile.write(parse_port(line) + '\n')

方法2:单循环处理所有行(更高效)

def parse_memrange(line):
    parts = line.split()
    base = [p.split('=')[1] for p in parts if p.startswith('BASEVALUE=')][0]
    instance = [p.split('=')[1] for p in parts if p.startswith('INSTANCE=')][0]
    slave = [p.split('=')[1] for p in parts if p.startswith('SLAVEBUSINTERFACE=')][0]
    return f"Memory: {instance} @ {base} (Bus: {slave})"

def parse_port(line):
    parts = line.split()
    clk = [p.split('=')[1] for p in parts if p.startswith('CLKFREQUENCY=')][0]
    sig = [p.split('=')[1] for p in parts if p.startswith('SIGNAME=')][0]
    return f"Port: {sig} - {clk} Hz"

with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    for line in infile:
        line = line.strip()
        if not line:
            continue
        if line.startswith('MEMRANGE'):
            outfile.write(parse_memrange(line) + '\n')
        elif line.startswith('PORT'):
            outfile.write(parse_port(line) + '\n')

AWK实现方案

一行命令完成需求,输出顺序为MEMRANGE在前、PORT在后:

awk '
/^MEMRANGE/ {
    for (i=2; i<=NF; i++) {
        split($i, arr, "=")
        if (arr[1] == "BASEVALUE") base = arr[2]
        if (arr[1] == "INSTANCE") inst = arr[2]
        if (arr[1] == "SLAVEBUSINTERFACE") bus = arr[2]
    }
    print "Memory: " inst " @ " base " (Bus: " bus ")"
}
/^PORT/ {
    for (i=2; i<=NF; i++) {
        split($i, arr, "=")
        if (arr[1] == "CLKFREQUENCY") clk = arr[2]
        if (arr[1] == "SIGNAME") sig = arr[2]
    }
    port_lines = port_lines "Port: " sig " - " clk " Hz\n"
}
END { print port_lines }
' input.txt > output.txt

SED实现方案

分两步处理,先提取MEMRANGE行,再追加PORT行结果:

# 提取并格式化MEMRANGE行,写入输出文件
sed -n 's/^MEMRANGE BASEVALUE=\([^ ]*\) INSTANCE=\([^ ]*\) SLAVEBUSINTERFACE=\([^ ]*\)/Memory: \2 @ \1 (Bus: \3)/p' input.txt > output.txt
# 提取并格式化PORT行,追加到输出文件
sed -n 's/^PORT CLKFREQUENCY=\([^ ]*\) SIGNAME=\([^ ]*\)/Port: \2 - \1 Hz/p' input.txt >> output.txt

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:17:54