跳转至

中文标点 → Edit 工具兜底方案

类型:rule(操作指南) 描述:含中文标点的旧 JSX/TS 改不动时,用 Python 切片替换 最后更新:2026-05-26 触发场景:Edit 工具报 String to replace not found / 改含中文 helper/label/comment 的旧代码

什么时候用

  • Edit 报 String to replace not found 且 old_string 看起来明明对
  • 改旧 React 组件的 helperText / label / comment(这些大概率是中文 + 全角标点)
  • 大块替换(>50 行)含中文的代码

为什么

Edit 工具不做全角/半角等价归一化。源码里:

半角(ASCII) 全角(Unicode)
( ) U+FF08/FF09
: U+FF1A
, U+FF0C
. U+3002
; U+FF1B
? U+FF1F
! U+FF01

手写 old_string 用了半角 → 文件里是全角 → string-not-found。

标准操作

小改动(1-3 行)

# 1) 打印目标行的精确字节
awk 'NR>=<开始行号> && NR<=<结束行号>' <文件路径>

# 2) 用鼠标复制输出里的中文标点,粘到 Edit 的 old_string 里

大块替换(推荐 — 不再猜)

# 1) 把新内容写到 /tmp/new.txt
cat > /tmp/new.txt << 'EOF'
... 整段新内容(任意标点都可,不影响) ...
EOF

# 2) 用 Python 切片做替换
python3 << 'PYEOF'
from pathlib import Path
p = Path("src/path/to/file.tsx")
src = p.read_text(encoding='utf-8')

# 用「文件里唯一存在的英文 / ASCII 锚点」定位区间
# 例如某个组件名 / 注释 marker / 函数签名
start = src.find("起始唯一锚点")
end = src.find("结束唯一锚点", start)
assert start >= 0 and end > start, f"锚点未找到 start={start} end={end}"

new_block = Path("/tmp/new.txt").read_text(encoding='utf-8')
p.write_text(src[:start] + new_block + src[end:], encoding='utf-8')
print(f"OK: replaced {end-start} bytes with {len(new_block)} bytes")
PYEOF

易错点

  • ⚠️ 不要连续猜 3 次以上:浪费 token + 时间,立即换 Python
  • ⚠️ 锚点要唯一:用「注释 marker」{/* ============ ... ============ */} 或者函数签名,不要用过于通用的字符串
  • ⚠️ 切片包含尾换行/tmp/new.txt 如果文件末尾多一个换行符,会多塞一行。可以 rstrip('\n')
  • ⚠️ bash heredoc 用 'EOF'(带引号):防止 $var 被 bash 展开

完成后必做

  • 验证文件结构(grep 锚点 / 对比行数)
  • pnpm compile 看有没有破坏语法

历史案例

版本 文件 教训
v0.10.13 (3 次踩) src/sections/settings/view/settings-view.tsx 想替换 customSocials helperText,里面 等,每行写: 是全角;连续猜 ASCII 3 次失败后改用 Python
v0.10.14 同上 进站策略子区改名,原文 (决定哪些网站要进、并发多大) 是全角括号;直接走 Python

反面教材(不要这么干)

试 1: 用 (...) 半角 → 失败
试 2: 用 (...) 全角 → 失败
试 3: 用 (...) + 调整其他字 → 失败
试 4: 又改一个标点 → 失败
试 5: ...

5 次手写 ≈ 1 次 Python。性价比一目了然。