移除FP YARN中的非放出文本
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Yarn Spinner 文件 line tag 去重工具
|
||||
|
||||
用法:
|
||||
python dedup_yarn_tags.py <文件路径> --from-node <节点名>
|
||||
python dedup_yarn_tags.py <文件路径> --from-line <行号>
|
||||
python dedup_yarn_tags.py <目录路径> --scan-all [--fix]
|
||||
|
||||
示例:
|
||||
python dedup_yarn_tags.py Assets/Resources/Yarn/FP_Day1_mid/Day1_mid.yarn --from-node 地铁ver4
|
||||
python dedup_yarn_tags.py Assets/Resources/Yarn/Fiction_Day1_begin/Fiction_Day1_begin.yarn --from-line 535 --fix
|
||||
python dedup_yarn_tags.py Assets/Resources/Yarn/ --scan-all
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def extract_line_tags(lines):
|
||||
"""从行列表中提取所有 line tag,返回 (行索引, tag) 列表"""
|
||||
tags = []
|
||||
pattern = re.compile(r'#line:[0-9a-fA-F]+')
|
||||
for idx, line in enumerate(lines):
|
||||
match = pattern.search(line)
|
||||
if match:
|
||||
tags.append((idx, match.group(), match.start(), match.end()))
|
||||
return tags
|
||||
|
||||
|
||||
def find_node_start_line(lines, node_title):
|
||||
"""根据节点 title 找到该节点开始的行索引(0-based)"""
|
||||
title_pattern = re.compile(r'^title:\s*' + re.escape(node_title) + r'\s*$')
|
||||
for idx, line in enumerate(lines):
|
||||
if title_pattern.match(line):
|
||||
# 找到 title 行,返回这一行(或返回 header 结束后的行)
|
||||
# 通常用户说"从某个节点开始",指的是该节点内容开始
|
||||
# 我们返回 title 行所在的位置即可,重复检测会自然跳过前面的 tag
|
||||
return idx
|
||||
return None
|
||||
|
||||
|
||||
def process_file(file_path, start_line_1based=None, node_title=None, fix=False, verbose=True):
|
||||
"""
|
||||
处理单个 Yarn 文件
|
||||
返回 (修改行数, 总重复数, 是否成功)
|
||||
start_line_1based: 1-based 行号,None 表示从头开始
|
||||
"""
|
||||
if not os.path.exists(file_path):
|
||||
if verbose:
|
||||
print(f"[错误] 文件不存在: {file_path}")
|
||||
return 0, 0, False
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
tags = extract_line_tags(lines)
|
||||
if not tags:
|
||||
if verbose:
|
||||
print(f"[信息] 未找到任何 line tag: {file_path}")
|
||||
return 0, 0, True
|
||||
|
||||
# 确定起始行索引(0-based)
|
||||
start_idx = 0
|
||||
if node_title:
|
||||
found = find_node_start_line(lines, node_title)
|
||||
if found is None:
|
||||
if verbose:
|
||||
print(f"[错误] 未找到节点 '{node_title}' in {file_path}")
|
||||
return 0, 0, False
|
||||
start_idx = found
|
||||
if verbose:
|
||||
print(f"[信息] 定位到节点 '{node_title}' 在第 {found + 1} 行")
|
||||
elif start_line_1based:
|
||||
start_idx = start_line_1based - 1
|
||||
if start_idx < 0:
|
||||
start_idx = 0
|
||||
if verbose:
|
||||
print(f"[信息] 从第 {start_line_1based} 行开始处理")
|
||||
|
||||
# 收集 start_idx 之前的所有 tag
|
||||
seen_tags = set()
|
||||
for idx, tag, _, _ in tags:
|
||||
if idx < start_idx:
|
||||
seen_tags.add(tag)
|
||||
|
||||
# 检测 start_idx 之后的重复
|
||||
duplicates = []
|
||||
for idx, tag, start_pos, end_pos in tags:
|
||||
if idx >= start_idx and tag in seen_tags:
|
||||
duplicates.append((idx, tag, start_pos, end_pos))
|
||||
elif idx >= start_idx:
|
||||
# 即使在处理范围内,也要记录已见,防止范围内自身重复
|
||||
seen_tags.add(tag)
|
||||
|
||||
if not duplicates:
|
||||
if verbose:
|
||||
print(f"[信息] 未发现重复 line tag: {file_path}")
|
||||
return 0, 0, True
|
||||
|
||||
if verbose:
|
||||
print(f"[发现] 找到 {len(duplicates)} 个重复 line tag:")
|
||||
for idx, tag, _, _ in duplicates:
|
||||
line_content = lines[idx].rstrip('\n')
|
||||
# 截断过长行
|
||||
display = line_content[:80] + "..." if len(line_content) > 80 else line_content
|
||||
print(f" 第 {idx + 1} 行: {tag} | {display}")
|
||||
|
||||
if not fix:
|
||||
if verbose:
|
||||
print(f"[提示] 使用 --fix 参数执行修改")
|
||||
return 0, len(duplicates), True
|
||||
|
||||
# 执行修改:从后往前替换,避免位置偏移
|
||||
modified_count = 0
|
||||
for idx, tag, _, _ in sorted(duplicates, key=lambda x: x[0], reverse=True):
|
||||
line = lines[idx]
|
||||
new_line = line.replace(tag, '', 1).rstrip()
|
||||
if not new_line.endswith('\n'):
|
||||
new_line += '\n'
|
||||
if new_line != line:
|
||||
lines[idx] = new_line
|
||||
modified_count += 1
|
||||
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.writelines(lines)
|
||||
|
||||
if verbose:
|
||||
print(f"[完成] 已修改 {modified_count} 行,移除 {len(duplicates)} 个重复 tag")
|
||||
|
||||
return modified_count, len(duplicates), True
|
||||
|
||||
|
||||
def scan_directory(dir_path, fix=False):
|
||||
"""扫描目录下所有 .yarn 文件"""
|
||||
if not os.path.isdir(dir_path):
|
||||
print(f"[错误] 目录不存在: {dir_path}")
|
||||
return
|
||||
|
||||
yarn_files = []
|
||||
for root, _, files in os.walk(dir_path):
|
||||
for f in files:
|
||||
if f.endswith('.yarn'):
|
||||
yarn_files.append(os.path.join(root, f))
|
||||
|
||||
if not yarn_files:
|
||||
print(f"[信息] 未找到 .yarn 文件: {dir_path}")
|
||||
return
|
||||
|
||||
print(f"[信息] 共找到 {len(yarn_files)} 个 .yarn 文件")
|
||||
total_duplicates = 0
|
||||
total_modified = 0
|
||||
|
||||
for fp in yarn_files:
|
||||
print(f"\n[扫描] {fp}")
|
||||
mod, dup, ok = process_file(fp, start_line_1based=1, fix=fix, verbose=True)
|
||||
if ok:
|
||||
total_modified += mod
|
||||
total_duplicates += dup
|
||||
|
||||
print(f"\n[汇总] 处理 {len(yarn_files)} 个文件,共发现 {total_duplicates} 个重复 tag,修改 {total_modified} 行")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Yarn Spinner line tag 去重工具',
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog='''
|
||||
示例:
|
||||
%(prog)s file.yarn --from-node 地铁ver4 --dry-run
|
||||
%(prog)s file.yarn --from-line 535 --fix
|
||||
%(prog)s dir/ --scan-all --fix
|
||||
'''
|
||||
)
|
||||
parser.add_argument('path', help='Yarn 文件或目录路径')
|
||||
parser.add_argument('--from-node', help='从指定节点 title 开始检测重复')
|
||||
parser.add_argument('--from-line', type=int, help='从指定 1-based 行号开始检测重复')
|
||||
parser.add_argument('--scan-all', action='store_true', help='扫描目录下所有 .yarn 文件(从第1行开始)')
|
||||
parser.add_argument('--fix', action='store_true', help='执行修改(默认仅预览)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
target_path = os.path.abspath(args.path)
|
||||
|
||||
if args.scan_all:
|
||||
scan_directory(target_path, fix=args.fix)
|
||||
elif os.path.isfile(target_path):
|
||||
if args.from_node and args.from_line:
|
||||
print("[错误] --from-node 和 --from-line 不能同时使用")
|
||||
sys.exit(1)
|
||||
mod, dup, ok = process_file(
|
||||
target_path,
|
||||
start_line_1based=args.from_line,
|
||||
node_title=args.from_node,
|
||||
fix=args.fix,
|
||||
verbose=True
|
||||
)
|
||||
if not ok:
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(f"[错误] 路径既不是文件也不是目录(或未提供 --scan-all): {target_path}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user