跨平台中文脚本编码规范
在 Windows、Linux/macOS、鸿蒙(OpenHarmony)等系统上生成含中文的脚本时,核心原则是让文件编码与解释器的默认解码一致。本规范覆盖主流脚本类型,目标是"既能用中文,又不乱码导致执行失败"。
触发条件
- 用户要求生成/编写脚本(
.ps1/.bat/.vbs/.sh/.bash/.zsh/.ets/.ts/.js/.py)且包含中文(注释、字符串、路径、输出)。 - 用户报告脚本因中文乱码执行失败:
SyntaxError: Non-UTF-8 code、PowerShell/cmd 中文乱码、shell 打不开、TS/JS 编译报错等。
按系统分类的推荐编码
| 系统/平台 | 脚本扩展名 | 推荐保存编码 | 关键措施 |
|---|---|---|---|
| Windows | .ps1 | UTF-8 带 BOM (utf-8-sig) | 关键是文件编码;运行前可设 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 |
| Windows | .bat / .cmd | GBK/ANSI,或 UTF-8 带 BOM + 首行 chcp 65001 >nul | 二选一;路径避免中文 |
| Windows | .vbs | GBK/ANSI,或 UTF-16LE 带 BOM | Windows Script Host 默认 ANSI;UTF-8 无 BOM 会乱码 |
| Linux / macOS | .sh / .bash / .zsh | UTF-8 无 BOM | LF 换行;chmod +x;shebang 如 #!/usr/bin/env bash |
| 鸿蒙(OpenHarmony 底层) | .sh | UTF-8 无 BOM | 开发者权限下终端可用;同 Linux shell 规范 |
| 鸿蒙(应用/生态层) | .ets / .ts / .js | UTF-8 无 BOM | ArkTS/TS/JS 编译器默认 UTF-8;LF 换行;路径建议英文 |
| 跨平台 | .py | UTF-8(带 BOM 也兼容) | 头部 # -*- coding: utf-8 -*-;读写显式 encoding='utf-8' |
生成流程(强制遵守)
1. Write/Edit 工具写入后的处理
- Write/Edit 默认写入 UTF-8 无 BOM。
- 必须带 BOM 的脚本(
.ps1、选择 UTF-8 方案的.bat)需要补 BOM:更直接的方式:用 Python 一次性生成# 给已写好的 .ps1 补 UTF-8 BOM(utf-8-sig) python -c "p='脚本.ps1'; open(p,'w',encoding='utf-8-sig').write(open(p,encoding='utf-8').read())".ps1内容并指定encoding='utf-8-sig',避免二次处理。
2. 避免中文文件名/路径
- Windows 脚本(
.ps1/.bat/.vbs)绝不使用中文文件名/路径。 - 其他平台尽量用英文路径;中文内容放变量,或放到独立的 UTF-8 数据文件中读取。
3. 换行符
- Windows 脚本:CRLF 或 LF 均可,CRLF 更原生。
- Linux / macOS / 鸿蒙 shell:必须是 LF。
- TS / JS / ETS / PY:推荐 LF。
4. 可执行权限
- Linux / macOS / 鸿蒙
.sh生成后必须可执行:chmod +x 脚本.sh。
各脚本最小模板
PowerShell .ps1
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$txt = Get-Content -Encoding UTF8 "data.txt"
Write-Host "中文输出正常"
bat / cmd
chcp 65001 >nul
echo 中文输出正常
VBScript .vbs(保存为 GBK/ANSI)
MsgBox "中文消息"
bash .sh
#!/usr/bin/env bash
# -*- coding: utf-8 -*-
set -euo pipefail
echo "中文输出正常"
zsh .zsh
#!/usr/bin/env zsh
# -*- coding: utf-8 -*-
echo "中文输出正常"
Python .py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
try:
sys.stdout.reconfigure(encoding='utf-8') # py3.7+
except Exception:
pass
with open('data.txt', encoding='utf-8') as f:
text = f.read()
print('中文输出正常')
TypeScript / ArkTS .ts / .ets
// 文件保存为 UTF-8 无 BOM,LF 换行
const msg: string = '中文消息';
console.info(msg);
JavaScript .js
// 文件保存为 UTF-8 无 BOM,LF 换行
const msg = '中文消息';
console.log(msg);
检测与修复
检测 BOM(PowerShell)
$hex = (Get-Content 文件.ps1 -AsByteStream -TotalCount 3 | ForEach-Object { '{0:X2}' -f $_ }) -join ' '
Write-Host "BOM=$hex (EF BB BF=UTF8带BOM, FF FE=UTF16, 空=无BOM)"
GBK → UTF-8 带 BOM 修复(PowerShell)
Get-Content 坏.ps1 -Encoding Default | Set-Content 好.ps1 -Encoding utf8BOM
CRLF → LF 转换(Git Bash / bash)
sed -i 's/\r$//' 脚本.sh
# 或
unix2dos 脚本.sh # 反向
批量修复(Python)
import os
recommended = {
'.ps1': 'utf-8-sig',
'.bat': 'utf-8-sig',
'.cmd': 'utf-8-sig',
'.vbs': 'gbk', # 或保持 ANSI
'.py': 'utf-8',
'.sh': 'utf-8',
'.bash': 'utf-8',
'.zsh': 'utf-8',
'.ts': 'utf-8',
'.js': 'utf-8',
'.ets': 'utf-8',
}
for fp in ['a.ps1', 'b.py']:
ext = os.path.splitext(fp)[1].lower()
target = recommended.get(ext, 'utf-8')
text = open(fp, encoding='gbk', errors='replace').read()
open(fp, 'w', encoding=target).write(text)
自检清单
- [ ]
.ps1/.bat(如选 UTF-8 方案)前 3 字节为EF BB BF - [ ]
.vbs保存为 GBK/ANSI 或 UTF-16LE - [ ]
.sh/.bash/.zsh无 BOM、LF 换行、已chmod +x - [ ]
.ets/.ts/.js无 BOM、LF 换行 - [ ] Python 含
# -*- coding: utf-8 -*-且读写显式encoding='utf-8' - [ ] Windows 脚本内无中文文件名/路径
- [ ] 非 Windows shell 脚本如需要执行权限已加
chmod +x
微信扫一扫