sublime正则处理i18n键值对的核心难点是键名唯一性、引号嵌套、跨行结构、多语言字符混排,须分步控制作用域,不可单正则通吃。

Sublime 正则替换处理 i18n 键值对,核心难点不在语法本身,而在于**键名唯一性、引号嵌套、跨行结构、多语言字符混排**这四点——任一失控都会导致错替、漏替或破坏 JSON/YAML 结构。必须分步控制作用域,不能靠一个正则通吃。
匹配带引号的键名(如 "login.title" 或 'auth.error.401')
直接搜 login\.title 会误中字符串内容或注释;不加引号边界又可能跨字段污染。安全做法是显式锚定引号和冒号/逗号上下文:
- 查找:
"([^"]+)"\s*:或'([^']+)'\s*:(分别匹配双/单引号包裹的键) - 若需同时支持两种引号,用:
(["'])([^"']+)\1\s*:,其中\1确保引号配对,$2捕获键名 - 注意:JSON 中键必须双引号,YAML 可单可双,但
["']会误匹配字符串值里的引号——所以务必先用In Selection限定在对象顶层 - 中文键(如
"用户登录")要求文件编码为 UTF-8(状态栏检查),否则[^"]+可能截断汉字
批量添加命名空间前缀(如从 "title" → "common.title")
不能无脑 Replace All,否则 "error.title" 会被改成 "common.error.title"。关键在限制匹配范围:
- 查找:
"([^".]+)"\s*:——[^".]+排除点号和引号,确保只匹配一级键名(如"title",不匹配"user.name") - 替换:
"common.$1"\s*:($1是原键名,\s*:复用原缩进和冒号) - 更严格场景(如只改
en.json里common块外的键):先手动选中目标区块 → 勾In Selection→ 再执行上述替换 - 若要跳过已有命名空间的键(如
"form.submit"),得加负向先行:"(?!common\.|form\.)([^".]+)"\s*:,但 Sublime 的 RE2 引擎不支持(?!...),此时只能人工分批或改用外部脚本
跨行值替换(如把 "welcome": "Hello, {name}!" 改成 "welcome": "欢迎,{name}!")
值含换行、占位符、标点时,.*? 极易贪婪吞掉后续键。必须用字符集明确收口:
- 查找:
"welcome"\s*:\s*("([^"]*)"|'([^']*)') —— 分别捕获双/单引号值,避免引号不匹配 - 替换:
"welcome": "欢迎,$2$3!"(<code>$2 和 <code>$3互斥,只有一组有值) - 若值含换行(如 YAML 多行字面量
description: |),则必须启用. matches newline,并改用:description:\s*\|\s*\n([\s\S]*?)\n(?=\w+:|$),用[\s\S]*?替代.*? - 中文标点注意:英文
!和中文!字节不同,替换时直接写中文符号即可,无需转义
校验替换后结构是否合法(JSON/YAML 格式不破)
正则无法验证语法,但可快速暴露常见破坏点:
- 替换后立即按
Ctrl+Shift+P→ 输入JSON Reindent(需安装 Pretty JSON 插件),格式错乱会报错 - 搜索
"[^"]*"[^:]*$(引号后无冒号的行)→ 找出键名未正确闭合的位置 - 搜索
:\s*["']?[^"']*["']?\s*,\s*["']→ 匹配值后紧跟另一个引号的行,大概率是逗号遗漏或引号错位 - 大文件操作前,务必用
Find in Files(Ctrl+Shift+F)预查匹配数,若返回 0 或远超预期,说明正则或作用域设错
最常被跳过的动作是:替换前没确认 status bar 显示 Regex 且 .* 图标已点亮;最隐蔽的坑是中文键名在 GBK 编码下被截断,导致 Find All 高亮位置偏移——这两点不检查,后面所有替换都不可信。











