我正在尝试编写一个能够自动从文件中删除UTF-8 BOM的脚本。 我无法检测文件是否有一个在第一个地方。 这是我的代码:
function has-bom { # Test if the file starts with 0xEF, 0xBB, and 0xBF head -c 3 "$1" | grep -P '\xef\xbb\xbf' return $? }
出于某种原因, head
似乎忽略了文件前面的BOM。 举个例子,运行这个
printf '\xef\xbb\xbf' > file head -c 3 file
将不会打印任何东西。
我试图寻找一个选项head --help
,让我解决这个问题,但没有运气。 有什么我可以做的这个工作?
首先,让我们来证明这个head
实际上正在工作:
$ printf '\xef\xbb\xbf' >file $ head -c 3 file $ head -c 3 file | hexdump -C 00000000 ef bb bf |...| 00000003
现在,我们来创建一个工作函数has_bom
。 如果你的grep
支持-P
,那么一个选项是:
$ has_bom() { head -c3 "$1" | LC_ALL=C grep -qP '\xef\xbb\xbf'; } $ has_bom file && echo yes yes
目前,只有GNU grep
支持-P
。
另一种选择是使用bash的$'...'
:
$ has_bom() { head -c3 "$1" | grep -q $'\xef\xbb\xbf'; } $ has_bom file && echo yes yes
ksh
和zsh
也支持$'...'
但是这个构造不是POSIX,而且dash
不支持它。
笔记:
使用显式return $?
是可选的。 该函数默认情况下会返回上一个命令运行的退出代码。
我用POSIX表格来定义函数。 这相当于bash窗体,但是如果你需要在另外一个shell下运行这个函数,那么这个窗口就不会有问题了。
bash确实接受使用这个字符-
在一个函数名中,但是这是一个有争议的特性。 我用更广泛接受的_
取代了它。 (有关此问题的更多信息,请参阅此答案 。)
grep
的-q
选项很安静,这意味着它仍然设置了正确的退出代码,但是它不会向stdout发送任何字符。