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
例えば拡張ASCIIセットでも\xe4
同様ですä
。しかし、制御文字と印刷可能文字(ASCII 範囲) 上記の grep コマンドは\xe4
文字と一致するはずです。なぜ grep 出力が得られないのでしょうか?
答え1
e4 75
確かに、これは不正な UTF8 シーケンスです。UTF8 では、最上位ニブルが 0xe であるバイトは、3 バイト シーケンスを導入します。このようなシーケンスの 2 番目のバイトは 0x75 にはなりません。なぜなら、その 2 番目のバイトの上位ニブル (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