Python文件解析异常:仅执行首个解析函数?求多工具解决方案
问题需求与故障现象
- 需求:从输入文件提取两类行的字段:
- 以
MEMRANGE开头的行:提取BASEVALUE、INSTANCE、SLAVEBUSINTERFACE的值,按指定格式输出 - 以
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
相关产品推荐
相关产品推荐

