如何修改Python代码生成符合要求的音系规则符号文件?
音系规则符号提取脚本修改方案
问题描述
现有名为lts_en_us_12.9.0_phonRules_Default copy.txt的音系规则文件,内容示例如下:
word {. .} {{;}} {rewrite} word {{#} .} {{$0} {;}} {rewrite} word {{;} .} {{$0} {;}} {rewrite} word {.pau .} {{$0} {;}} {rewrite} word {. #} {{;} {$1}} {rewrite} word {. {;}} {{;} {$1}} {rewrite} word {. .pau} {{;} {$1}} {rewrite} word {{;} {;}} {{;}} {rewrite} aux-verb-reduction {{;} k aI1 n d {;} {^1 &} v {;}} {{$0} k aI1 n . d & {$8}} {optional} aux-verb-reduction {{;} w A1 n t {;} t {u1 &} {;}} {{$0} w A1 . n & {$8}} {optional} aux-verb-reduction {{;} l E1 t {;} m i1 {;}} {{$0} l E1 . m i {$7}} {optional} aux-verb-reduction {{;} g I1 v {;} m i1 {;}} {{$0} g I1 . m i {$7}} {optional}
需要生成symbols.txt文件,核心要求:
- 默认包含
ε和.,固定排在顶部 - 过滤每行开头的规则名(如
word、aux-verb-reduction)和结尾的rewrite/optional,仅提取中间的左右模式内容 - 处理
$n标记:替换为对应左侧模式中索引为n的元素 - 最终符号按字母顺序排序
现有代码未过滤无关内容、未处理$n替换、未做排序,输出不符合要求:
symbols = [("ε", 0), (".", 1)] with open("lts_en_us_12.9.0_phonRules_Default copy.txt", "r") as f: for line in f: parts = line.strip().split(" ") for part in parts: if part not in [s[0] for s in symbols]: symbols.append((part, len(symbols))) with open("symbols.txt", "w") as f: for symbol in symbols: f.write(f"{symbol[0]} {symbol[1]}\n")
修改思路
- 精准解析每行结构,分离规则名、左右模式和操作符,仅保留左右模式
- 解析模式中的元素,处理
{}包裹的多元素场景 - 替换右模式中的
$n为左模式对应索引的元素 - 用集合自动去重收集所有符号
- 按要求排序:默认符号置顶,其余按字母顺序排列
- 分配索引并写入目标文件
完整修改代码
import re def parse_pattern(pattern_str): """解析模式字符串,提取所有元素(支持{}包裹的多元素)""" elements = [] # 匹配{}包裹的内容或单个独立元素 matches = re.findall(r'\{([^{}]+)\}|([^{}\s]+)', pattern_str) for match in matches: if match[0]: # 拆分{}内的多元素 inner_elements = match[0].split() elements.extend(inner_elements) elif match[1]: elements.append(match[1]) return elements # 初始化符号集合,加入默认符号 symbol_set = {"ε", "."} # 读取规则文件 with open("lts_en_us_12.9.0_phonRules_Default copy.txt", "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue # 拆分每行:规则名 左模式 右模式 操作符(不拆分{}内部的空格) parts = re.split(r'(?<!\{)\s(?!\})', line, maxsplit=3) if len(parts) < 4: continue _, left_pattern, right_pattern, _ = parts # 解析左模式元素列表 left_elements = parse_pattern(left_pattern) # 收集左模式所有元素 for elem in left_elements: symbol_set.add(elem) # 处理右模式的$n替换 right_elements = parse_pattern(right_pattern) processed_right = [] for elem in right_elements: if elem.startswith("$") and elem[1:].isdigit(): idx = int(elem[1:]) if 0 <= idx < len(left_elements): processed_right.append(left_elements[idx]) else: processed_right.append(elem) # 收集替换后的右模式元素 for elem in processed_right: symbol_set.add(elem) # 排序:默认符号置顶,其余按字母顺序排列 sorted_symbols = ["ε", "."] + sorted([s for s in symbol_set if s not in {"ε", "."}]) # 写入symbols.txt with open("symbols.txt", "w", encoding="utf-8") as f: for idx, symbol in enumerate(sorted_symbols): f.write(f"{symbol} {idx}\n")
代码说明
- parse_pattern函数:通过正则解析模式字符串,不管是单个元素还是
{}包裹的多元素,都能准确提取 - 符号去重:用集合存储符号,自动避免重复添加
- 行拆分逻辑:使用正则拆分,确保不会拆分
{}内部的空格,精准分离出左右模式 - $n替换:检查右模式元素是否为
$n格式,合法的索引会替换为左模式对应元素 - 排序处理:固定
ε和.在顶部,剩余符号按字母顺序排序 - 索引分配:从0开始为每个符号分配唯一索引,写入文件
输出示例
ε 0 . 1 # 2 ; 3 . # 4 . ; 5 . .pau 6 .pau . 7 ; . 8 ; ; 9 # . 10 # ; 11 k 12 aI1 13 n 14 d 15 ^1 & 16 v 17 w 18 A1 19 t 20 u1 & 21 l 22 E1 23 m 24 i1 25 g 26 I1 27
内容的提问来源于stack exchange,提问作者Taolan Jiaohaer
相关产品推荐
相关产品推荐

