应使用正则[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]批量删除危险控制字符,该表达式排除\t(\x09)和\n(\x0a)以保缩进与换行,再单独用[\r(?!\n)]清理孤立\r,最后用xxd验证字节级干净。

怎么用正则一次清掉 \x00 到 \x1f 里危险的控制字符
Python 报 SyntaxError: Non-UTF-8 code starting with '\x00' 或 invalid byte sequence,八成是文件混入了真实不可见字节,不是空格、不是制表符,而是 \x00、\x07、\x1b 这类 C0 控制字符。它们藏在代码中间,python -m py_compile test.py 一跑就崩,但 Sublime 界面里根本看不见。
别用 [\x00-\x1f]——它会误删 \t(\x09)和 \n(\x0a),直接破坏缩进和换行。正确表达式是:
[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]
这个范围排除了 \t 和 \n,只干掉真正该删的“有毒”字节。操作步骤:
- Ctrl+H 打开替换面板,勾选右下角
.*(启用正则) - 查找框粘贴上面那串正则,替换框留空
- 点
Replace All,不是Find All后再手动点 —— 后者容易漏
注意:\r(即显示为 ^M)不在这个范围内,得单独处理。
为什么 \r 要单独删,且不能只搜 ^M
^M 是 Sublime 对 \r 的显示符号,不是字符本身。你在查找框里输 ^M,Sublime 默认当普通文本匹配,根本找不到隐藏的 \r 字节。必须用正则搜 \r 本体。
但不能无差别删所有 \r:Windows 文件里的 \r\n 是合法换行,删掉 \r 就只剩 \n,变成 Unix 风格;可如果 \r 单独出现在行中或行尾(比如 print("hello")\r),那就是残留垃圾,必须清除。
稳妥做法分两步:
- 先统一换行风格:右下角状态栏点
CRLF→Convert to Unix line endings - 再搜
\r(?!\n)(负向先行断言,匹配后面不跟\n的\r),替换成空
这样既保留了 \r\n 中的 \r(已转成 \n),又清掉了所有孤零零的 \r。
删完怎么验证真干净了,别信状态栏显示
Sublime 状态栏写的是 UTF-8,只代表当前解码方式,不证明字节合法。文件里还躺着 \x00 或孤立 \r,它照样显示正常。
终端里跑这句才是硬核验证:
xxd test.py | head -n 5
看输出里有没有:
-
00(对应\x00) - 单独的
0d(即\r,后面没紧跟着0a) - 连续出现的
0c 0b等异常组合
如果只有 0d 0a(\r\n)或 0a(\n),说明干净了。再补一刀 python -m py_compile test.py,不报错才算过关。
怎么预防下次再混进来
每次从网页、微信、Word 粘代码,都可能带控制字符。事后清理是下策。
在 Preferences → Settings – User 里加这两行:
"paste_text_filter": "all",<br>"trim_automatic_white_space": true
paste_text_filter: "all" 会让 Sublime 在粘贴瞬间自动剥离 \r、\x00、\x1b 等所有控制字符,不是显示过滤,是真删;trim_automatic_white_space 顺手干掉行尾空格,对 Python 安全无害。
这个配置生效即时,不用重启。但注意:它只管粘贴,不管拖拽或导入文件——那些场景还得靠 xxd + 正则兜底。











