我发现了一个被认为是 UTF-8 编码的文本文件的有问题的序列。奇怪的是 grep 似乎无法匹配这个非 ASCII 行。
$ iconv -f utf8 -t iso88591 corrupt_part.txt --output corrupt_part.txt.conv
iconv: illegal input sequence at position 8
$ cat corrupt_part.txt
Oberallg�u
$ grep -P -n '[^\x00-\x7F]' corrupt_part.txt
$ od -h corrupt_part.txt
0000000 624f 7265 6c61 676c 75e4 0a20
0000014
\xe4
例如,ä
在扩展 ASCII 集中也是如此。然而,过滤控制和可打印字符(ASCII 范围) 上面的 grep 命令应该与该\xe4
字符匹配。为什么我没有得到任何 grep 输出?
答案1
e4 75
确实是非法的utf8序列。在utf8中,最高半字节等于0xe的字节引入了三字节序列。该序列的第二个字节不能是 0x75,因为第二个字节的高位半字节 (0x7) 不在 0x8 和 0xb 之间。
这解释了为什么 iconv 拒绝该文件作为无效的 utf8。也许它已经是 iso8859-1 了?
有关 utf8 编码的摘要,请参阅此维基百科表
至于你的 grep 问题,也许如果你指定 C/POSIX 语言环境,其中字符相当于字节:
LC_ALL=C grep -P -n '[^\x00-\x7F]' corrupt_part.txt
使用旧的 Ubuntu 系统、GNU grep 和使用 en_US.UTF-8 语言环境的环境:
$ od -h bytes
0000000 624f 7265 6c61 676c 75e4 0a20
0000014
$ grep -P '[^\x00-\x7F]' bytes | od -h
0000000 624f 7265 6c61 676c 75e4 0a20
0000014
$ LC_ALL=C grep -P '[^\x00-\x7F]' bytes | od -h
0000000 624f 7265 6c61 676c 75e4 0a20
0000014