OSX使用sed移除UTF-8中的BOM

最近遇到的一个问题是在OSX和iOS上,带BOM的UTF-8编码格式的文件(主要是Excel导出来的lua配表)无法正常工作。于是在打包脚本中增加了一个环节去除各UTF-8编码文件中可能出现的BOM头。

使用grep查询

使用grep查询包含BOM的文件。BOM(Byte Order Mark )在UTF-8中其实是位于文件开头的三个字节,用16进制表示是\xEF\xBB\xBF

1
grep -r -i -l $'^\xEF\xBB\xBF' .

其中-r表示递归查询,-i表示忽略大小写,-l表示列出符合要求的文件名。$'^\xEF\xBB\xBF'是正则表达式,表示匹配位于行首的\xEF\xBB\xBF,最后的.表示当前目录。

使用sed替换

查询到包含BOM头的文件后,使用sed来处理这三个字节即可(替换为空):

1
grep -r -i -l $'^\xEF\xBB\xBF' . | xargs sed -i 's/^\xEF\xBB\xBF//g'

使用xargs将查询到的文件名列表传给sed,执行替换,也可以直接使用sed并指定文件名来替换单个文件中的BOM头:

1
sed -i 's/^\xEF\xBB\xBF//g' a.txt

其中-i表示直接修改读取到的文本的内容,'s/^\xEF\xBB\xBF//g's表示替换内容,被替换的内容与替换内容使用左斜杠分隔,如使用's/a/b/'的格式表示将a替换为b^\xEF\xBB\xBF表示位于行首的BOM字节,g表示替换行内所有的匹配。

在OSX使用gnu-sed

本来有上边这些就可以解决问题了,但是在mac上使用上边的sed命令,多半是会报错的。即便是给-i加了参数,十六进制表示的三个字节总是替换不掉的。

这是因为OSX上附带的sed是Unix上的sed,而前边用到的是Linux上的gnu-sed。靠谱的做法是安装gnu-sed,有两种做法供选择:

一种是使用gsed来区分OSX上自带的sed命令,首先使用Home Brew安装:

1
brew install gnu-sed

然后在使用时直接用gsed就好了,比如之前的命令,就变成了:

1
gsed -i 's/^\xEF\xBB\xBF//g' a.txt

另一种方式是安装gnu-sed并且设置sed命令直接使用gnu-sed,同样使用Home Brew安装,但是附带参数:

1
brew install gnu-sed --with-default-names

完成安装之后,在.bash_profile中增加:

1
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"

然后执行:

1
source .bash_profile

即可直接使用gnu版本的sed命令了。

REFERENCE