import os, sys, re sys.stdout.reconfigure(encoding='utf-8') base_dir = "resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문" job_words = [ "포장공", "보통인부", "특별인부", "철근공", "보링공", "기계설비공", "철공", "조경공", "착암공", "용접공", "배관공", "할석공", "석공", "줄눈공", "미장공", "도장공", "방수공", "타일공", "내장공", "석면해체공", "궤도공", "중급기술자", "초급기술자", "고급기술자" ] files = [ "제1장_공통.md", "제2장_토목.md", "제3장_건축.md", "제4장_기계설비.md" ] total_fixed = 0 for fname in files: fpath = os.path.join(base_dir, fname) with open(fpath, 'r', encoding='utf-8') as f: lines = f.readlines() new_lines = [] file_fixes = 0 for idx, line in enumerate(lines): line_str = line.strip() if not (line_str.startswith('|') and line_str.endswith('|')): new_lines.append(line) continue cells = [c.strip() for c in line_str.split('|')[1:-1]] # Skip divider or note if all(re.match(r'^:?-+:?$', c) for c in cells if c) or (cells and cells[0] in ["비고", "비 고", "주", "[주]"]): new_lines.append(line) continue # Find which cell has multiple job titles job_cell_idx = -1 detected_jobs = [] for c_idx, c in enumerate(cells): # Check if this cell contains multiple known job words # Notice in markdown it may be spaced: "철 근 공 보 통 인 부" # Normalize spaces inside tokens # Split tokens: toks = c.split() # If tokens end with common job characters if len(toks) >= 2 and all(any(tok.endswith(end) for end in ["공", "부", "사", "자"]) for tok in toks): # Candidate job cell # Check if next cells have matching "인 인..." and numbers job_cell_idx = c_idx detected_jobs = toks break # Also handle spaced letters like "포 장 공 보 통 인 부" # Combine characters and match c_nospace = c.replace(" ", "") matched_jobs = [] cur_str = c_nospace for jw in sorted(job_words, key=len, reverse=True): while jw in cur_str: matched_jobs.append(jw) cur_str = cur_str.replace(jw, "", 1) if len(matched_jobs) >= 2 and cur_str == "": # Reconstruct in order of original string ordered_jobs = [] pos = 0 while pos < len(c_nospace): found = False for jw in sorted(job_words, key=len, reverse=True): if c_nospace[pos:].startswith(jw): ordered_jobs.append(jw) pos += len(jw) found = True break if not found: break if len(ordered_jobs) >= 2: job_cell_idx = c_idx detected_jobs = ordered_jobs break if job_cell_idx != -1 and len(detected_jobs) >= 2: N = len(detected_jobs) # Find unit cell and qty cell unit_cell_idx = -1 qty_cell_idx = -1 for c_idx in range(job_cell_idx + 1, len(cells)): toks = cells[c_idx].split() if len(toks) == N and all(t in ["인", "대", "hr", "시간", "식", "-"] for t in toks): unit_cell_idx = c_idx break if unit_cell_idx != -1: # Find qty cell(s) # Check if there are columns with N numbers can_split = False col_splits = {} # c_idx -> list of N values for c_idx in range(unit_cell_idx + 1, len(cells)): toks = cells[c_idx].split() if len(toks) == N and all(re.match(r'^-?\d+(?:,\d+)?(?:\.\d+)?$', t) for t in toks): col_splits[c_idx] = toks can_split = True if can_split: # Generate N rows # In other cells, first row gets the cell value, other rows get empty "" unit_toks = cells[unit_cell_idx].split() for r_idx in range(N): new_row_cells = [] for c_idx in range(len(cells)): if c_idx == job_cell_idx: new_row_cells.append(detected_jobs[r_idx]) elif c_idx == unit_cell_idx: new_row_cells.append(unit_toks[r_idx]) elif c_idx in col_splits: new_row_cells.append(col_splits[c_idx][r_idx]) else: # First row keeps existing value, subsequent rows get empty string if r_idx == 0: new_row_cells.append(cells[c_idx]) else: new_row_cells.append("") new_line_str = "| " + " | ".join(new_row_cells) + " |\n" new_lines.append(new_line_str) file_fixes += 1 total_fixed += 1 continue new_lines.append(line) if file_fixes > 0: print(f"{fname}: fixed {file_fixes} multi-worker squashed rows") with open(fpath, 'w', encoding='utf-8') as f: f.writelines(new_lines) print(f"Total multi-worker rows fixed in 유지관리부문: {total_fixed}")