const fs = require('fs'); const inputPath = '/Users/joey-xd/sites/pipi-learn/platform-pipi/packages/voice-production/data/char/char_introduce_v2.json'; const data = JSON.parse(fs.readFileSync(inputPath, 'utf8')); // ========== 修复词典 ========== // 格式: char → 常用词/短语,用于生成 "char,word的char" // 覆盖 "X字的X" 和 "X的X" 两类问题 const wordFixes = { // --- "X字的X" 类 (294个) --- 迟: '迟到', 局: '局面', 改: '改变', 张: '张开', 忌: '禁忌', 际: '国际', 陆: '陆地', 阿: '阿谀', 陈: '陈列', 阻: '阻止', 附: '附近', 坠: '坠落', 妓: '歌妓', 妙: '美妙', 妖: '妖怪', 姊: '姊妹', 妨: '妨碍', 妒: '嫉妒', 努: '努力', 忍: '忍耐', 抽: '抽屉', 拐: '拐弯', 拖: '拖延', 者: '读者', 拍: '拍手', 顶: '头顶', 拆: '拆除', 拎: '拎包', 拥: '拥抱', 抵: '抵达', 拘: '拘留', 势: '势力', 抱: '拥抱', 拄: '拄杖', 垃: '垃圾', 拉: '拉开', 拦: '拦截', 幸: '幸福', 拌: '搅拌', 拧: '拧开', 歧: '分歧', 肯: '肯定', 齿: '牙齿', 些: '一些', 卓: '卓越', 虎: '老虎', 虏: '俘虏', 肾: '肾脏', 贤: '贤明', 尚: '高尚', 旺: '兴旺', 具: '工具', 味: '味道', 果: '水果', 昆: '昆虫', 国: '国家', 哎: '哎呀', 咕: '咕噜', 昌: '昌盛', 呵: '呵护', 疙: '疙瘩', 柑: '柑橘', 枯: '枯萎', 柄: '把柄', 栋: '栋梁', 相: '互相', 查: '检查', 柏: '柏树', 栅: '栅栏', 柳: '柳树', 柱: '柱子', 柿: '柿子', 栏: '栏杆', 柠: '柠檬', 树: '大树', 勃: '蓬勃', 要: '需要', 柬: '请柬', 咸: '咸淡', 威: '威力', 歪: '歪斜', 韭: '韭菜', 背: '背后', 战: '战争', 点: '点头', 虐: '虐待', 临: '临时', 览: '浏览', 竖: '竖立', 省: '省份', 削: '削苹果', 尝: '品尝', 昧: '愚昧', 盹: '打盹', 是: '是非', 盼: '盼望', 眨: '眨眼', 哇: '哇塞', 哄: '哄堂大笑', 哑: '哑巴', 显: '显然', 很: '很好', 猎: '打猎', 猫: '猫咪', 凰: '凤凰', 猖: '猖狂', 猛: '猛烈', 祭: '祭祀', 馅: '馅饼', 馆: '博物馆', 凑: '凑合', 减: '减少', 毫: '毫米', 烹: '烹饪', 庶: '庶民', 麻: '麻烦', 庵: '尼姑庵', 痊: '痊愈', 痒: '发痒', 痕: '痕迹', 廊: '走廊', 康: '健康', 谓: '所谓', 谚: '谚语', 谜: '谜语', 逮: '逮捕', 敢: '勇敢', 尉: '上尉', 屠: '屠宰', 弹: '子弹', 隋: '隋朝', 堕: '堕落', 随: '随便', 蛋: '鸡蛋', 隅: '角隅', 隆: '隆重', 隐: '隐藏', 婚: '结婚', 婶: '婶婶', 婉: '婉转', 颇: '颇多', 颈: '颈椎', 替: '替代', 揍: '揍人', 款: '款式', 堪: '堪称', 塔: '宝塔', 搭: '搭建', 堰: '堤堰', 揩: '揩油', 越: '超越', 趁: '趁机', 趋: '趋势', 超: '超级', 揽: '包揽', 堤: '堤坝', 提: '提高', 博: '博学', 揭: '揭开', 喜: '欢喜', 彭: '彭姓', 揣: '揣测', 装: '装扮', 蛮: '野蛮', 就: '成就', 敦: '敦厚', 斌: '文武双全', 痘: '痘痘', 痢: '痢疾', 痪: '瘫痪', 痛: '痛苦', 童: '儿童', 竣: '竣工', 阔: '辽阔', 善: '善良', 翔: '飞翔', 羡: '羡慕', 普: '普通', 粪: '粪便', 尊: '尊重', 奠: '奠基', 道: '道路', 榄: '橄榄', 想: '想象', 槐: '槐树', 榆: '榆树', 楼: '楼房', 概: '大概', 赖: '依赖', 酬: '报酬', 感: '感觉', 碍: '阻碍', 尴: '尴尬', 矮: '矮小', 辞: '辞职', 稚: '幼稚', 稠: '稠密', 颓: '颓废', 愁: '忧愁', 筹: '筹划', 简: '简单', 筷: '筷子', 毁: '毁灭', 舅: '舅舅', 鼠: '老鼠', 催: '催促', 傻: '傻瓜', 像: '好像', 躲: '躲藏', 魁: '魁梧', 衙: '衙门', 微: '微小', 馍: '馍馍', 叠: '重叠', 缠: '缠绕', 缤: '缤纷', 剿: '围剿', 静: '安静', 碧: '碧绿', 璃: '玻璃', 赘: '累赘', 熬: '熬夜', 墙: '围墙', 墟: '废墟', 嘉: '嘉奖', 摧: '摧毁', 赫: '显赫', 截: '截断', 誓: '发誓', 境: '环境', 摘: '采摘', 摔: '摔倒', 撇: '撇开', 聚: '聚集', 蜡: '蜡烛', 蝇: '苍蝇', 蜘: '蜘蛛', 蝉: '蝉鸣', 嘛: '干嘛', 嘀: '嘀咕', 赚: '赚钱', 锹: '铁锹', 锻: '锻炼', 镀: '镀金', 舞: '跳舞', 舔: '舔嘴', 稳: '稳定', 熏: '熏陶', 箕: '簸箕', 算: '计算', 箩: '箩筐', 管: '管理', 箫: '洞箫', 舆: '舆论', 薄: '薄饼', 颠: '颠倒', 翰: '翰墨', 噩: '噩梦', 橱: '橱柜', 橙: '橙子', 橘: '橘子', 整: '整齐', 融: '融化', 瓢: '瓢虫', 醒: '清醒', 霍: '霍然', 霎: '霎时', 辙: '车辙', 冀: '希冀', 餐: '餐厅', 嘴: '嘴巴', 踱: '踱步', 蹄: '马蹄', 蹂: '蹂躏', 靡: '奢靡', 癣: '皮癣', 瓣: '花瓣', 羹: '肉羹', 鳖: '甲鳖', 爆: '爆炸', 疆: '边疆', 鬓: '鬓角', 壤: '土壤', 馨: '温馨', 耀: '闪耀', 躁: '急躁', 蠕: '蠕动', 嚼: '咀嚼', 嚷: '叫嚷', 巍: '巍峨', 籍: '书籍', 鳞: '鱼鳞', 魔: '魔法', 糯: '糯米', // --- "X的X" 类 (47个) --- 你: '你好', 系: '关系', 茎: '茎叶', 画: '画画', 鱼: '鲤鱼', 狗: '小狗', 底: '底部', 油: '石油', 泡: '泡泡', 空: '天空', 钠: '钠元素', 看: '看见', 剑: '宝剑', 总: '总是', 给: '给予', 起: '起来', 根: '树根', 党: '党员', 哦: '哦哦', 圆: '圆形', 钾: '钾元素', 铁: '铁路', 铅: '铅笔', 秤: '秤杆', 般: '一般', 爱: '爱心', 狼: '灰狼', 谁: '谁人', 球: '足球', 硅: '硅谷', 做: '做事', 您: '您好', 假: '真假', 率: '效率', 锅: '铁锅', 锌: '锌元素', 鹅: '白鹅', 然: '自然', 粥: '稀粥', 鼓: '打鼓', 搬: '搬家', 摇: '摇晃', 搞: '搞笑', 塘: '池塘', 摊: '摊贩', 聘: '聘请', 慢: '慢慢', }; // ========== 修复逻辑 ========== let fixCount = 0; function fixIntroduce(ch, intro) { // 检测 "X,X字的X" 模式 const m1 = intro.match(/^(.),(.)字的\1$/); if (m1 && m1[1] === m1[2]) { const okPairs = ['文字', '写字', '名字', '签字', '数字']; if (!okPairs.includes(m1[2] + '字')) { if (wordFixes[ch]) { fixCount++; return `${ch},${wordFixes[ch]}的${ch}`; } } } // 检测 "X,X的X" 自引用模式 const m2 = intro.match(/^(.),\1的\1$/); if (m2) { if (wordFixes[ch]) { fixCount++; return `${ch},${wordFixes[ch]}的${ch}`; } } return intro; } Object.entries(data).forEach(([ch, val]) => { if (ch.startsWith('_')) return; if (typeof val[0] === 'string') { // 单音字: [pinyin, meaning, introduce] val[2] = fixIntroduce(ch, val[2]); } else { // 多音字: [[pinyin, meaning, introduce], ...] val.forEach((r) => { r[2] = fixIntroduce(ch, r[2]); }); } }); // ========== 写入 ========== fs.writeFileSync(inputPath, JSON.stringify(data, null, 2), 'utf8'); console.log(`修复完成: ${fixCount} 个 introduce 已更新`); // ========== 验证 ========== const dataCheck = JSON.parse(fs.readFileSync(inputPath, 'utf8')); let remaining = 0; Object.entries(dataCheck).forEach(([ch, val]) => { if (ch.startsWith('_')) return; function check(intro) { const m1 = intro.match(/^(.),(.)字的\1$/); if ( m1 && m1[1] === m1[2] && !['文字', '写字', '名字', '签字', '数字'].includes(m1[2] + '字') ) remaining++; const m2 = intro.match(/^(.),\1的\1$/); if (m2) remaining++; } if (typeof val[0] === 'string') check(val[2]); else val.forEach((r) => check(r[2])); }); console.log(`剩余问题: ${remaining}`);