import os, sys, re sys.stdout.reconfigure(encoding='utf-8') target_files = [ # 02_토목부문 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제1장_도로포장공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제2장_하천공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제3장_터널공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제4장_궤도공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제5장_강구조공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제6장_관부설및접합공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제7장_항만공사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제8장_지반조사.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/02_토목부문/제9장_측량.md', # 05_유지관리부문 'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제1장_공통.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제2장_토목.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제3장_건축.md', 'resources/knowledge/original/원가계산/건설공사_표준품셈/05_유지관리부문/제4장_기계설비.md', # 04_기계설비부문 제13장 'resources/knowledge/original/원가계산/건설공사_표준품셈/04_기계설비부문/제13장_플랜트설비공사.md', ] print("=== Scanning for Overlapped / Duplicated Squashed Rows in Same Table ===") overlap_cases = [] for fpath in target_files: fname = os.path.basename(fpath) with open(fpath, 'r', encoding='utf-8') as f: lines = f.readlines() tables = [] cur_t = [] cur_start = 0 for idx, l in enumerate(lines): line_str = l.strip() if line_str.startswith('|') and line_str.endswith('|'): if not cur_t: cur_start = idx + 1 cur_t.append((idx + 1, line_str)) else: if cur_t: tables.append((cur_start, cur_t)) cur_t = [] if cur_t: tables.append((cur_start, cur_t)) for t_start, t_rows in tables: # Separate header and data rows data_rows = [] for lno, r_str in t_rows: cells = [c.strip() for c in r_str.split('|')[1:-1]] if all(re.match(r'^:?-+:?$', c) for c in cells if c): continue if cells and cells[0] in ["비고", "비 고", "주", "[주]"]: continue data_rows.append((lno, r_str, cells)) if len(data_rows) < 3: continue # For each row in the table, check if it is a "squashed row" # (contains multiple words or numbers in a single cell) for r_idx, (lno, r_str, cells) in enumerate(data_rows): # Check if any cell has multi-values is_squashed = False multi_words = [] for c in cells: # E.g. 2 or more distinct words (length >= 2) in the cell w_list = [w for w in c.split() if len(w) >= 2 and w not in ["-", "·", "ㆍ"]] if len(w_list) >= 2: is_squashed = True multi_words.extend(w_list) if not is_squashed: continue # Now, check if these multi_words appear in PRECEDING rows of the SAME table as separate entries! matched_preceding_rows = [] for prev_idx in range(r_idx): prev_lno, prev_str, prev_cells = data_rows[prev_idx] prev_words = set(w for c in prev_cells for w in c.split() if len(w) >= 2) # Does prev_words share words with multi_words? overlap = prev_words.intersection(set(multi_words)) # Filter out generic words like '인부', '보통인부' overlap = {w for w in overlap if w not in ["인부", "보통인부", "특별인부", "플랜트", "설비공", "용접공", "배관공"]} if overlap: matched_preceding_rows.append((prev_lno, list(overlap), prev_str[:60])) if len(matched_preceding_rows) >= 2: # This squashed row matches 2 or more preceding distinct rows in the same table! overlap_cases.append({ 'file': fname, 'line': lno, 'table_start': t_start, 'squashed_row': r_str[:90], 'matched_preceding': matched_preceding_rows }) print(f"Total squashed rows overlapping with preceding rows in same table: {len(overlap_cases)}") for oc in overlap_cases: print(f"\n[{oc['file']}:L{oc['line']}] (Table starting at L{oc['table_start']})") print(f" Squashed row: {oc['squashed_row']}") print(f" Matches {len(oc['matched_preceding'])} preceding rows:") for plno, ow, pstr in oc['matched_preceding'][:5]: print(f" L{plno} (overlap: {ow}): {pstr}")