import re import os from collections import Counter, defaultdict from tqdm import tqdm # ================= 配置路径 ================= BASE_DIR = r"D:\Tools\lab_t3" FILE_MAIN = os.path.join(BASE_DIR, "dyhdc(v5)08.txt") FILE_ELEMENTS = os.path.join(BASE_DIR, "元素代码节表.txt") FILE_TRAD_SIMP = os.path.join(BASE_DIR, "繁简词头对照表.txt") FILE_OUT_MAIN = os.path.join(BASE_DIR, "dyhdc(v5)09.txt") FILE_OUT_CASE1 = os.path.join(BASE_DIR, "第一种情况_繁简对照组清单.txt") FILE_OUT_CASE2 = os.path.join(BASE_DIR, "第二种情况_繁简对照组清单.txt") FILE_OUT_CASE3 = os.path.join(BASE_DIR, "第三种情况_繁简对照组清单.txt") FILE_OUT_CASE4 = os.path.join(BASE_DIR, "第四种情况_繁简对照组清单.txt") FILE_OUT_MATCH3 = os.path.join(BASE_DIR, "第三种情况_匹配对照组清单.txt") FILE_OUT_MATCH4 = os.path.join(BASE_DIR, "第四种情况_匹配对照组清单.txt") # ================= 1. 加载辅助数据 ================= print("正在加载辅助数据...") # 加载元素代码节表(按长度降序排序,防止部分替换错误) elements_list = [] with open(FILE_ELEMENTS, 'r', encoding='utf-8') as f: elements_list = [line.strip() for line in f if line.strip()] elements_list.sort(key=len, reverse=True) # 加载繁简词头对照表(支持多对一、一对多) # 构建字典:简体词头 -> 对应的繁体词头集合 simp_to_trads = defaultdict(set) with open(FILE_TRAD_SIMP, 'r', encoding='utf-8') as f: for line in f: if '=' in line: trad, simp = line.strip().split('=', 1) simp_to_trads[simp].add(trad) def clean_elements(text): """剔除元素代码节表中的元素""" for el in elements_list: text = text.replace(el, "") return text # ================= 2. 定义词条解析类 ================= class DictEntry: def __init__(self, original_line): self.line = original_line.rstrip('\n') # 1. 提取词头(归一化处理:提取第一个匹配词头,剔除和【】) hw_matches = re.findall(r'【.*?】', self.line) if hw_matches: self.headword = re.sub(r'<\d+>', '', hw_matches[0]).replace('【', '').replace('】', '') else: self.headword = "" # 2. 提取词身节块(以词头文节为切分节点,切割后剔除元素代码) raw_segments = re.split(r'【.*?】', self.line) self.segments = [clean_elements(seg) for seg in raw_segments] # 假性词身节块(切分出的第一个片段) self.pseudo_seg = self.segments[0] if self.segments else "" # 真实词身节块(其余所有片段) self.true_segs = self.segments[1:] if len(self.segments) > 1 else [] # 词身文节(所有节块串接) self.body_text = "".join(self.segments) # 3. 提取词条子节 (A 内的内容并剔除元素代码节) raw_items = re.findall(r'(.*?)', self.line) self.sub_entries = set(clean_elements(item) for item in raw_items if clean_elements(item)) self.retained_case = 0 # 标记位,用于记录最终归属阶段 # ================= 3. 解析主文档 ================= entries = [] hw_to_idx = defaultdict(list) # 词头到行索引的映射字典 print("正在解析主词典文本...") with open(FILE_MAIN, 'r', encoding='utf-8') as f: for i, line in tqdm(enumerate(f), desc="解析行"): entry = DictEntry(line) entries.append(entry) hw_to_idx[entry.headword].append(i) # ================= 4. 分阶段严格顺次排查 ================= s_processed = set() # 全局锁:已被判定归属的简体词条行索引,一旦入库永不二次跨阶段判定 removed_simp_indices = set() # 记录应被剔除(情况1、2)的行索引 case1_pairs = [] case2_pairs = [] case3_pairs = [] case4_pairs = [] # 【阶段一】词身文节完全相同(重合) for simp, trads in tqdm(simp_to_trads.items(), desc="第一阶段 (排查情况1)"): if simp not in hw_to_idx: continue for s_idx in hw_to_idx[simp]: if s_idx in s_processed: continue s_entry = entries[s_idx] phase_matched = False # 遍历该简体词头对应的所有繁体词头 for trad in trads: if trad not in hw_to_idx: continue # 遍历对应繁体词头的所有文本行(允许同阶段内多次匹配并全部记录) for t_idx in hw_to_idx[trad]: if s_idx == t_idx: continue t_entry = entries[t_idx] if t_entry.body_text == s_entry.body_text: case1_pairs.append((t_entry.line, s_entry.line)) phase_matched = True if phase_matched: s_processed.add(s_idx) # 彻底完成当前阶段后,锁定该简体词条 removed_simp_indices.add(s_idx) # 记为待剔除 # 【阶段二】词身文节不同,乱序串接后重合 for simp, trads in tqdm(simp_to_trads.items(), desc="第二阶段 (排查情况2)"): if simp not in hw_to_idx: continue for s_idx in hw_to_idx[simp]: if s_idx in s_processed: continue # 完美屏蔽阶段1锁定的项 s_entry = entries[s_idx] phase_matched = False for trad in trads: if trad not in hw_to_idx: continue for t_idx in hw_to_idx[trad]: if s_idx == t_idx: continue t_entry = entries[t_idx] if Counter(t_entry.segments) == Counter(s_entry.segments): case2_pairs.append((t_entry.line, s_entry.line)) phase_matched = True if phase_matched: s_processed.add(s_idx) # 锁定 removed_simp_indices.add(s_idx) # 记为待剔除 # 【阶段三】乱序不可重合,但除假性节块外,个别节块相同 for simp, trads in tqdm(simp_to_trads.items(), desc="第三阶段 (排查情况3)"): if simp not in hw_to_idx: continue for s_idx in hw_to_idx[simp]: if s_idx in s_processed: continue # 完美屏蔽阶段1、2锁定的项 s_entry = entries[s_idx] phase_matched = False for trad in trads: if trad not in hw_to_idx: continue for t_idx in hw_to_idx[trad]: if s_idx == t_idx: continue t_entry = entries[t_idx] t_true_set = set(t_entry.true_segs) - {""} s_true_set = set(s_entry.true_segs) - {""} if t_true_set & s_true_set: # 存在交集 case3_pairs.append((t_entry.line, s_entry.line)) phase_matched = True if phase_matched: s_processed.add(s_idx) # 锁定 entries[s_idx].retained_case = 3 # 记为情况3保留 # 【阶段四】除假性节块外,个别节块完全不重合 for simp, trads in tqdm(simp_to_trads.items(), desc="第四阶段 (排查情况4)"): if simp not in hw_to_idx: continue for s_idx in hw_to_idx[simp]: if s_idx in s_processed: continue # 完美屏蔽阶段1、2、3锁定的项 s_entry = entries[s_idx] phase_matched = False for trad in trads: if trad not in hw_to_idx: continue for t_idx in hw_to_idx[trad]: if s_idx == t_idx: continue t_entry = entries[t_idx] t_true_set = set(t_entry.true_segs) - {""} s_true_set = set(s_entry.true_segs) - {""} if not (t_true_set & s_true_set): # 完全无交集 case4_pairs.append((t_entry.line, s_entry.line)) phase_matched = True if phase_matched: s_processed.add(s_idx) # 锁定 entries[s_idx].retained_case = 4 # 记为情况4保留 # ================= 5. 导出 v09 文本与情况1-4对照组清单 ================= print("\n正在生成新文本 dyhdc(v5)09.txt...") v09_indices = [i for i in range(len(entries)) if i not in removed_simp_indices] with open(FILE_OUT_MAIN, 'w', encoding='utf-8') as f: for idx in v09_indices: f.write(entries[idx].line + "\n") def write_pairs(filename, pairs): with open(filename, 'w', encoding='utf-8') as f: for i, (t_line, s_line) in enumerate(pairs, 1): f.write(f"===== 组 {i} =====\n") f.write(f"[繁体词头词条]{t_line}\n") f.write(f"[简体词头词条]{s_line}\n\n") write_pairs(FILE_OUT_CASE1, case1_pairs) write_pairs(FILE_OUT_CASE2, case2_pairs) write_pairs(FILE_OUT_CASE3, case3_pairs) write_pairs(FILE_OUT_CASE4, case4_pairs) # ================= 6. 滤重及交叉匹配 ================= def run_post_matching(target_case, desc): # 步骤A:对满足当前阶段保留条件的简体行进行【文本内容层面的彻底滤重】 unique_lines = set() dedup_entries = [] for idx in v09_indices: if entries[idx].retained_case == target_case: line_text = entries[idx].line if line_text not in unique_lines: unique_lines.add(line_text) dedup_entries.append(entries[idx]) # 步骤B:对滤重后的目标行展开全局匹配 results = [] for s_entry in tqdm(dedup_entries, desc=desc): target_subs = s_entry.sub_entries matches = [] # 遍历 v09 所有的词条文本行进行比对 for idx in v09_indices: other_entry = entries[idx] if other_entry.line == s_entry.line: continue # 排除自身比较 other_subs = other_entry.sub_entries # 如果两者都有子节内容 if target_subs and other_subs: intersect = target_subs & other_subs if len(intersect) > 0: if target_subs == other_subs: matches.append(("完全重合", other_entry.line)) else: matches.append(("部分重合", other_entry.line)) results.append({ 'target': s_entry.line, 'matches': matches }) return results def write_matches(filename, results): with open(filename, 'w', encoding='utf-8') as f: for i, res in enumerate(results, 1): f.write(f"===== 组 {i} =====\n") f.write(f"[目标词条] {res['target']}\n") if not res['matches']: f.write(" -> [匹配词条]:\n 未匹配到其他词条。\n") else: f.write(" -> [匹配词条]:\n") for m_type, m_line in res['matches']: f.write(f" ({m_type}) {m_line}\n") f.write("\n") print("\n开始执行全局子节乱序匹配(已启用目标行滤重)...") match3_results = run_post_matching(3, "子节交叉匹配 (情况3)") write_matches(FILE_OUT_MATCH3, match3_results) match4_results = run_post_matching(4, "子节交叉匹配 (情况4)") write_matches(FILE_OUT_MATCH4, match4_results) print("\n全部任务处理完成!各级文档和明细清单已导出至:", BASE_DIR)