使用SED修复UTF-16文件换行符替换命令失效问题
问题根源
你的命令没生效是三个问题叠加导致的:
- 正则表达式存在书写错误:匹配规则里写的
\x0\x0\0x0A存在笔误,第三个转义序列多打了反斜杠,实际会被解析为「两个空字节 + 八进制转义的空字节 + 字面字符串x0A」,完全匹配不到你要找的0x00 0x00 0x0A三字节序列。 - sed的工作模式天生不适合处理这个场景:绝大多数环境下的sed默认按单字节文本行模式工作,会把单字节
0x0A识别为行终止符,读取内容时遇到0x0A就会截断当前行,根本不会把跨位置的0x00 0x00和后面的0x0A识别为连续序列做匹配。同时sed原生不支持UTF-16编码,处理双字节编码文件时很容易把字符拆碎,造成二次损坏。 - 转义语法兼容性差:
\xNN格式的十六进制字节转义只有高版本GNU sed支持,macOS自带的BSD sed等常见环境下的sed根本不识别这个写法,会直接把\x0当成普通字符串处理。
可行修复方案
不要用sed做UTF-16文件的二进制字节替换,选以下两种稳定方案:
- 直接做二进制字节替换:用perl以二进制模式一次性读取全文件做匹配替换,不会被换行符截断,也不会破坏编码:
perl -i.bak -pe 's/\x00\x00\x0A/\x00\x0A/g' -0777 "test.h"
命令执行后会自动生成test.h.bak备份文件,替换逻辑完全匹配你要的字节替换规则。
- 编码转换后处理:先把UTF-16文件转成通用的UTF-8编码,修正换行后再转回UTF-16,适合后续还要对文件做其他文本修改的场景:
# 小端序UTF-16(Windows平台常见)转UTF-8,大端序把UTF-16LE换成UTF-16BE即可 iconv -f UTF-16LE -t UTF-8 test.h > test_temp.h # 确认内容正常后转回UTF-16 iconv -f UTF-8 -t UTF-16LE test_temp.h > test_fixed.h
提示:如果你的UTF-16文件带BOM头,直接把编码参数写为
UTF-16即可,iconv会自动识别BOM判断端序,不需要手动指定LE/BE。
内容的提问来源于stack exchange,提问作者magol
相关产品推荐
相关产品推荐

