
作業中のファイル内で見つかった奇妙な文字を特定しようとしています:
$ cat file
�
$ od file
0000000 005353
0000002
$ od -c file
0000000 353 \n
0000002
$ od -x file
0000000 0aeb
0000002
ファイルは ISO-8859 エンコードを使用しているため、UTF-8 に変換できません。
$ iconv -f ISO-8859 -t UTF-8 file
iconv: conversion from `ISO-8859' is not supported
Try `iconv --help' or `iconv --usage' for more information.
$ iconv -t UTF-8 file
iconv: illegal input sequence at position 0
$ file file
file: ISO-8859 text
私の主な質問は、ここの出力をどのように解釈すればよいかということですod
。私はこのページ005353
これにより、異なる文字表現間で変換できますが、 「16 進コード ポイント」として は卓
正しくないように思われ、また、 0aeb
「16 進コード ポイント」として は૫
間違っているように思われることがわかります。
では、3 つのオプション ( 355
、005353
、0aeb
) のいずれかを使用して、それらが表す文字を確認するにはどうすればよいでしょうか?
はい、Unicode ツールで試してみましたが、これも有効な UTF 文字ではないようです。
$ uniprops $(cat file)
U+FFFD ‹�› \N{REPLACEMENT CHARACTER}
\pS \p{So}
All Any Assigned Common Zyyy So S Gr_Base Grapheme_Base Graph X_POSIX_Graph
GrBase Other_Symbol Print X_POSIX_Print Symbol Specials Unicode
Unicode U+FFFD 文字の説明を理解している限りでは、これは実際の文字ではなく、破損した文字のプレースホルダーです。ファイルが実際には UTF-8 でエンコードされていないので、これは理にかなっています。
答え1
ファイルには16進数でEBと0Aの2バイトが含まれています。ファイルは1文字あたり1バイトの文字セットを使用している可能性があります。ISO-8859-1; その文字セットでは、EB は ë です。
$ printf "\353\n" | iconv -f ISO-8859-1
ë
他の候補としてはδが挙げられますコードページ 437、Ùでコードページ 850...
od -x
この場合、エンディアンのため、出力は混乱を招きます。より良いオプションは、-t x1
単一バイトを使用する です。
$ printf "\353\n" | od -t x1
0000000 eb 0a
0000002
od -x
od -t x2
一度に 2 バイトを読み取り、リトルエンディアン システムでは逆の順序でバイトを出力するマップです。
このような有効な UTF-8 ではない (または UTF-8 ファイルとして解釈しても意味をなさない) ファイルに遭遇した場合、そのエンコード (および文字セット) を自動的に判別する確実な方法はありません。コンテキストが役立ちます。過去 20 年以内に欧米の PC で作成されたファイルであれば、ISO-8859-1、-15 (ユーロ版)、または Windows-1252 でエンコードされている可能性が高くなります。それより古いファイルであれば、CP-437 および CP-850 が候補となる可能性があります。東ヨーロッパのシステム、ロシアのシステム、またはアジアのシステムからのファイルは、私があまり知らないさまざまな文字セットを使用します。次に、EBCDIC があります... は、が認識しているiconv -l
すべての文字セットを一覧表示しますiconv
。そこから試行錯誤して進めることができます。
(一時期、私は CP-437 と ATASCII のほとんどを暗記していました。あの頃はよかったです。)
答え2
はのod
略です8進ダンプ、005353
2 バイトは 8 進ワードとして、od -x
は0aeb
16 進ワードとして、ファイルの実際の内容は 2 バイトeb
と0a
16 進数で、この順序になります。
したがって、 と005353
は両方とも、0aeb
単に「16 進コード ポイント」として解釈することはできません。
0a
は改行コード (LF) であり、eb
エンコードによって異なります。file
エンコードは推測に過ぎず、何でもかまいません。ファイルの出所などの詳細情報がなければ、見つけ出すのは困難です。
答え3
テキスト ファイルの文字セットを 100% の精度で推測することは不可能です。
次のようなツールシャルデ、ファイアフォックス、ファイル -i明示的に文字セット情報が定義されていない場合 (たとえば、HTML のヘッダーに meta charset=... が含まれている場合は、処理が簡単になります)、テキストが十分に大きい場合はそれほど悪くないヒューリスティックを使用しようとします。
以下では、chardet
(必要に応じてpip install chardet
/ apt-get install python-chardet
) を使用して文字セット検出を示します。
$ echo "in Noël" | iconv -f utf8 -t latin1 | chardet
<stdin>: windows-1252 with confidence 0.73
適切な文字セット候補が得られたら、 または同様のものを使用して、iconv
ファイルrecode
の文字セットを「アクティブな」文字セット (私の場合は utf-8) に変更し、正しく推測されたかどうかを確認できます...
iconv -f windows-1252 -t utf-8 file
一部の文字セット (iso-8859-3、iso-8859-1 など) には多くの共通文字があるため、最適な文字セットが見つかったかどうかを確認するのは簡単ではない場合があります...
したがって、関連するテキスト (XML など) にメタデータを関連付けることが非常に重要です。
答え4
#!/bin/bash
#
# Search in a file, a known (part of a ) String (i.E.: Begrüßung),
# by testing all encodings
#
[[ $# -ne 2 ]] && echo "Usage: encoding-finder.sh FILE fUnKy_CHAR_FOR_SURE_IN_FILE" && exit
FILE=$1
PATTERN=$2
for enc in $( iconv -l | sed 's/..$//')
do
iconv -f $enc -t UTF-8 $FILE 2>/dev/null | grep -m 1 $PATTERN && echo $enc
done
たとえば、Begrung という単語を含むファイルを取得した場合、Begrüßung を意味している可能性があると推測できます。そのため、既知のすべてのエンコードで変換し、適切に変換するエンコードが見つかるかどうかを確認します。
通常、適合すると思われるエンコーディングは複数あります。
長いファイルの場合は、数百ページを変換するのではなく、スニペットを切り取ることがあります。
だから私はそれを
encodingfinder.sh FILE Begrüßung
そして、スクリプトは、既知のエンコーディングで変換することによって、どれが「Begrüßung」を生成するかをテストします。
このような文字を見つけるには、通常 less が役立ちます。なぜなら、奇妙な文字は目立つことが多いからです。文脈から、検索する適切な単語は通常推測できます。しかし、16 進エディターでこれがどのバイトであるかを確認し、エンコーディングの無限のテーブルにアクセスして、違反者を見つけるのは望ましくありません。:)