最近遇到的一个问题是在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
命令了。