Linux 如何在Bash中检测文件是否具有UTF-8 BOM?
我正在尝试编写一个脚本,该脚本将自动从文件中删除UTF-8 BOM。我很难检测文件是否有一个放在首位。这是我的密码:Linux 如何在Bash中检测文件是否具有UTF-8 BOM?,linux,bash,unix,encoding,utf-8,Linux,Bash,Unix,Encoding,Utf 8,我正在尝试编写一个脚本,该脚本将自动从文件中删除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' &
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\u bom
。如果您的grep
支持-P
,那么一个选项是:
$ has_bom() { head -c3 "$1" | LC_ALL=C grep -qP '\xef\xbb\xbf'; }
$ has_bom file && echo yes
yes
目前,只有GNUgrep
支持-p
另一个选项是使用bash的$'…'
:
$ has_bom() { head -c3 "$1" | grep -q $'\xef\xbb\xbf'; }
$ has_bom file && echo yes
yes
ksh
和zsh
也支持$“…”
但此构造不是POSIX,并且dash
不支持它
注:
返回$?
是可选的。默认情况下,该函数将返回上次命令运行的退出代码-
,但这是一个有争议的特性。我将其替换为更为广泛接受的。
。(有关此问题的更多信息,请参阅。)grep
的-q
选项使其安静,这意味着它仍然设置了正确的退出代码,但不会向stdout发送任何字符我在第一行中应用了以下内容:
read c
if (( "$(printf "%d" "'${c:0:1}")" == 65279 )) ; then c="${c:1}" ; fi
这只是从变量中删除BOM。在纯bash中,解决方案可以是:
function has_bom() {
local bom
LANG=C read -r -N 3 bom < "$1"
[[ "$bom" == $'\xef\xbb\xbf' ]]
}
无BOM时的测试:
$ F=test.utf8
$ head -c 5 "$F" | hd
00000000 c3 a9 6c c3 a9 |..l..|
$ has_bom "$F" && echo "$F has a BOM" || echo "$F has no BOM"
test.utf8 has no BOM
哈,从来都不知道Bash支持十六进制字符串文字。无论如何,谢谢你的回答!您好,
head-c3文件| hextump-c
行中的-c
是做什么的?前一个似乎是1)限制输出的字符数2)限制行号(可能)为0000000和0000003;但后者将输出(应该是“be bf”等)变成替换标记。我正在使用bash并在Windows下生成的文本文件上进行测试,原始编码=GB18030。谢谢。@CrazyFroghead-c3文件
将文件
的前三个字符写入标准输出hextump-C
以人性化的方式将这些字符格式化为十六进制。@John1024谢谢我找到了手册!虽然我在文本文件的开头用代码生成BOM表,但这很奇怪,但是这个命令没有看到它。@John1024这可能是我应该做的。我将自己再次检查代码。我一定是弄错了。谢谢你的帮助!
$ F=test.utf8
$ head -c 5 "$F" | hd
00000000 c3 a9 6c c3 a9 |..l..|
$ has_bom "$F" && echo "$F has a BOM" || echo "$F has no BOM"
test.utf8 has no BOM