4. 检查并修复A2L文件中的非法字符
任务说明
A2L文件本质上是文本文件,但解析器通常要求其内容严格限定在ASCII字符集内,且字符串字面量中的转义序列必须合法。当文件中混入全角空格、中文标点、不可见控制字符或类似 \xZZ 的非法转义时,解析器会在词法分析阶段直接报错或产生乱码。本案例的目标是编写一个Python脚本,扫描指定A2L文件,定位所有非ASCII字符及非法转义序列,并自动替换为合法ASCII字符,输出修复后的文件供解析器读取。
实现思路
脚本按行读取A2L文件,对每一行执行两类检查:
- 非ASCII字符:将行编码为ASCII时失败的字符即为非法字符。根据常见错误类型做映射替换(如全角逗号→半角逗号,中文引号→英文引号),无法映射的字符统一替换为下划线。
- 非法转义序列:在双引号字符串内查找
\x后跟非十六进制字符的组合,以及孤立的\后跟非\\、\"等合法转义的情况,将其中的反斜杠替换为正斜杠或删除。
修复完成后,脚本会报告每处替换的位置和内容,并将结果写入新文件。
完整代码
import re
import sys
# 常见非ASCII字符的映射表
CHAR_MAP = {
'\u3000': ' ', # 全角空格
'\uff0c': ',', # 全角逗号
'\u3002': '.', # 全角句号
'\uff08': '(', # 全角左括号
'\uff09': ')', # 全角右括号
'\u201c': '"', # 左双引号
'\u201d': '"', # 右双引号
'\u2018': "'", # 左单引号
'\u2019': "'", # 右单引号
'\uff1a': ':', # 全角冒号
'\uff1b': ';', # 全角分号
}
def fix_non_ascii(line, line_no, report):
"""替换非ASCII字符,返回修复后的行"""
result = []
for ch in line:
if ord(ch) > 127:
if ch in CHAR_MAP:
result.append(CHAR_MAP[ch])
report.append(f"行{line_no}: 非ASCII字符 U+{ord(ch):04X} ({ch}) → {CHAR_MAP[ch]}")
else:
result.append('_')
report.append(f"行{line_no}: 非ASCII字符 U+{ord(ch):04X} ({ch}) → _")
else:
result.append(ch)
return ''.join(result)
def fix_bad_escapes(line, line_no, report):
"""修复字符串中的非法转义序列"""
# 匹配 \x 后跟非十六进制字符的情况
line = re.sub(r'\\x(?![0-9A-Fa-f]{2})', '/x', line)
# 匹配孤立反斜杠(后跟非合法转义字符)
line = re.sub(r'\\(?![\\"nrt])', '/', line)
return line
def process_file(input_path, output_path):
report = []
fixed_lines = []
with open(input_path, 'r', encoding='utf-8') as f:
for line_no, line in enumerate(f, 1):
original = line
# 先处理非ASCII字符
line = fix_non_ascii(line, line_no, report)
# 再处理非法转义
line = fix_bad_escapes(line, line_no, report)
if line != original:
report.append(f"行{line_no}: 内容已修改")
fixed_lines.append(line)
with open(output_path, 'w', encoding='ascii') as f:
f.writelines(fixed_lines)
return report
if __name__ == '__main__':
if len(sys.argv) != 3:
print("用法: python fix_a2l_chars.py <输入文件.a2l> <输出文件.a2l>")
sys.exit(1)
input_file = sys.argv[1]
output_file = sys.argv[2]
changes = process_file(input_file, output_file)
if changes:
print(f"共修复 {len(changes)} 处问题:")
for item in changes:
print(f" {item}")
else:
print("未发现非法字符,文件已原样复制。")
print(f"输出文件: {output_file}")
运行与验证
运行方式:
python fix_a2l_chars.py 原始文件.a2l 修复后文件.a2l
验证步骤:
- 准备一个包含非法字符的测试A2L文件,例如在
MEASUREMENT块描述中混入全角逗号和中文引号,在注释字符串中加入\xZZ。 - 运行上述脚本,观察输出报告是否列出了所有非法字符的位置和替换结果。
- 检查输出文件:用十六进制编辑器或
file命令确认输出文件为纯ASCII编码(无UTF-8多字节序列)。 - 用A2L解析器(如INCA或第三方库
a2lparser)尝试解析输出文件,确认不再报词法错误。
通过条件:脚本报告的所有替换位置与文件中实际存在的非法字符一一对应;输出文件可通过 python -c "open('修复后文件.a2l','rb').read().decode('ascii')" 验证无解码异常;解析器能成功读取修复后的文件。
常见问题
- 误替换合法反斜杠:A2L中路径字符串可能包含
\\表示单个反斜杠,正则已排除\\和\"等合法转义,不会误伤。 - 非ASCII字符出现在注释中:脚本不区分注释与代码,统一替换。若注释中的非ASCII字符不影响解析,可手动保留,但本脚本为通用安全起见一律替换。
- 文件编码:输入文件需为UTF-8编码。若原始文件为GBK等编码,请先转换为UTF-8再运行脚本。