iconv 的基本用法
iconv 来自 glibc(macOS 与部分 BSD 也有各自实现),作用是把一种字符编码的字节流转换成另一种。用法是 iconv -f 源编码 -t 目标编码 [文件],结果输出到标准输出,因此通常配合重定向或 -o 写文件。它的行为可以概括为「逐字符映射」:源编码解码成字符,再按目标编码编码,遇到无法映射的输入或无法表示的输出就会报错中止,因此它是排查编码问题最常用的验证工具。
基本信息
| 基本语法 | iconv -f 源编码 -t 目标编码 [-o 输出文件] [输入文件] |
|---|---|
| 常见选项 | -c 丢弃非法输入字符(有损);-l 列出支持的编码名 |
| 默认行为 | 遇到非法序列或无法表示字符时报错并中止,退出码非零 |
| 常用验证 | iconv -f UTF-8 -t UTF-8 file > /dev/null 用来严格校验 |
| 实现差异 | GNU libiconv 与 macOS / BusyBox 支持的编码名与扩展语法不同 |
| 编码命名 | 同一编码常有多个别名,可用 iconv -l 查询确切的写法 |
典型使用场景
- 历史文件批量转码:把 GBK 目录整体转成 UTF-8,保持目录结构
- 严格校验:把输入按同一编码转一遍,用是否报错判断字节是否合法
- 数据管道环节:在脚本里作为显式转码步骤,替代程序里的隐式转换
- CI 检查:提交的文本文件不允许出现非法序列,用 iconv 做门禁
- 排查辅助:把可疑内容转成另一编码,观察是否变可读,从而判定原始编码
常用命令示例
常用命令示例
iconv -l | grep -i -E '^(gbk|gb18030|utf-8)' # 先确认本机支持的编码名写法
iconv -f GBK -t UTF-8 legacy.txt -o utf8.txt # 正常转换:输出到新文件
iconv -f UTF-8 -t UTF-8 legacy.txt > /dev/null # 严格校验:报错即存在非法 UTF-8 序列
iconv -f GBK -t UTF-8 -c legacy.txt -o out.txt # 有损模式:丢弃非法字符,事后必须核对
find ./data -name '*.txt' -print0 | while IFS= read -r -d '' f; do
iconv -f GBK -t UTF-8 "$f" -o "$f.utf8" && mv "$f.utf8" "$f" # 批量就地替换,务必先整体备份
done选项与风险对照
| 选项 | 作用 | 风险 |
|---|---|---|
| -f | 指定源编码 | 源编码判断错会得到另一种乱码 |
| -t | 指定目标编码 | 目标编码表示能力不足时字符被丢弃或报错 |
| -o | 输出到文件 | 与输入同名时会截断源文件(就地覆盖风险) |
| -c | 丢弃非法输入字符 | 静默丢数据,退出码可能仍为零 |
| -l | 列出支持的编码 | 不同实现支持的名称与数量不同 |
| (无) | 默认输出到标准输出 | 重定向到目标文件时部分写出会留下半成品 |
转码是有损与无损的分界:源与目标编码都能表示全部字符时是无损往返;目标编码表示能力不足时,字符会被丢弃或替换,且这个过程通常不可逆。转码前用样本确认覆盖范围,比事后补救便宜得多。
绝不就地覆盖:iconv 读到一半报错时,目标文件可能已经写入了部分内容。安全做法是输出到临时文件,校验通过后再原子替换(mv 覆盖),并在此之前对原文件做备份。
编码名在不同实现上写法不同:Linux 上 GB2312 常被当作 GBK 处理,macOS 的 iconv 部分中文编码名与 GNU 版本不一致。脚本要在多平台运行时应先执行一次编码名探测,而不是硬编码别名。