import sys, os, re, json sys.stdout.reconfigure(encoding='utf-8') with open('scratch/confirmed_attached_headers.json', 'r', encoding='utf-8') as f: fixes = json.load(f) fixes_by_file = {} for fix in fixes: f = fix['file'] if f not in fixes_by_file: fixes_by_file[f] = [] fixes_by_file[f].append(fix) base_dir = "resources/knowledge/original/원가계산/건설공사_표준품셈" stats = [] for rel_file, file_fixes in fixes_by_file.items(): fpath = os.path.join(base_dir, rel_file) with open(fpath, 'r', encoding='utf-8') as f: text = f.read() lines = text.split('\n') orig_count = len(lines) # Sort fixes descending by line file_fixes_sorted = sorted(file_fixes, key=lambda x: (x['line'], x['matched_pos']), reverse=True) modified_lines = list(lines) fixed_count = 0 for fix in file_fixes_sorted: l_idx = fix['line'] - 1 sec_num = fix['sec_num'] cur_line = modified_lines[l_idx] # Regex to find exact boundary: not space, not quote/bracket, then sec_num + space pattern = re.compile(rf'([^\s#\-\*\>\|\(‘\'"\[])({re.escape(sec_num)}\s+)') m = pattern.search(cur_line) if m: new_line = cur_line[:m.start(2)] + '\n' + cur_line[m.start(2):] modified_lines[l_idx] = new_line fixed_count += 1 new_text = '\n'.join(modified_lines) new_lines = new_text.split('\n') added_lines = len(new_lines) - orig_count with open(fpath, 'w', encoding='utf-8') as f: f.write(new_text) stats.append({ "file": rel_file, "original_lines": orig_count, "new_lines": len(new_lines), "lines_added": added_lines, "fixes_applied": fixed_count }) print(f"Fixed {rel_file}: {fixed_count} headers restored (lines {orig_count} -> {len(new_lines)})") with open('scratch/headers_fix_stats.json', 'w', encoding='utf-8') as f: json.dump(stats, f, ensure_ascii=False, indent=2) total_fixes = sum(s['fixes_applied'] for s in stats) total_lines_added = sum(s['lines_added'] for s in stats) print(f"\n=== Completed: {total_fixes} attached headers restored, {total_lines_added} lines added across {len(stats)} files ===")