web-dev-qa-db-ja.com

どうすれば奇妙なキャラクターを特定できますか?

私が作業しているファイルで見つけた奇妙な文字を識別しようとしています:

$ 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つのオプション(355005353または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でエンコードされていないため、これは理にかなっています。

10
terdon

ファイルには2バイト、EBと0Aが16進数で含まれています。ファイルが ISO-8859-1 ;のような、文字ごとに1バイトの文字セットを使用している可能性があります。その文字セットでは、EBはëです。

$ printf "\353\n" | iconv -f ISO-8859-1
ë

他の候補は、δ- コードページ437 、Ù- コードページ85 ...

od -xの出力は、エンディアンのため、この場合は混乱します。より良いオプションはシングルバイトを使用する-t x1です:

$ printf "\353\n" | od -t x1
0000000 eb 0a
0000002

od -xは、一度に2バイトを読み取るod -t x2にマップし、リトルエンディアンシステムでは、バイトを逆の順序で出力します。

このような、UTF-8として有効ではない(またはUTF-8ファイルとして解釈されても意味がない)ファイルに遭遇した場合、そのエンコーディング(および文字セット)を自動的に決定する確実な方法はありません。コンテキストが役立ちます。それが過去20年間にWestern PCで作成されたファイルである場合、ISO-8859-1、-15(ユーロバリアント)、またはWindows-1252でエンコードされている可能性がかなりあります。それより古い場合は、CP-437とCP-850が候補になる可能性があります。東ヨーロッパのシステム、ロシアのシステム、アジアのシステムのファイルは、私がよく知らないさまざまな文字セットを使用します。次に、EBCDICがあります... iconv -lは、iconvが認識しているすべての文字セットをリストし、そこから試行錯誤することができます。

(ある時点で、私はCP-437とATASCIIのほとんどを暗記していました。それらは当時のことでした。)

22
Stephen Kitt

odoctal dumpの省略形なので、005353は2バイトの8進数のワード、od -x0aebはWordの16進数で、実際のファイルの内容は2バイトですebおよび0a 16進数で、この順序で。

だから両方005353および0aebを単に「16進コードポイント」として解釈することはできません。

0aは改行(LF)であり、ebはエンコーディングによって異なります。 fileはエンコーディングを推測しているだけなので、何でもかまいません。ファイルがどこから来たのかなどの詳細情報がなければ、見つけるのは難しいでしょう。

5
dirkt

テキストファイルの文字セットを100%正確に推測することは不可能です。

chardetfirefoxfile -iなどのツールは、明示的な文字セット情報が定義されていない場合(HTMLにメタ文字セット=が含まれる場合など)。 ..頭の中で、物事は簡単です)テキストが十分に大きい場合、それほど悪くない発見的手法を使用しようとします。

以下では、chardetpip install chardet/apt-get install python-chardet 必要であれば)。

$ echo "in Noël" | iconv -f utf8 -t latin1  | chardet
<stdin>: windows-1252 with confidence 0.73

適切な文字セット候補が得られたら、iconvrecodeなどを使用して、ファイルの文字セットを「アクティブ」な文字セット(私の場合はutf-8)に変更し、正しく推測されたかどうかを確認します。 ..

iconv -f windows-1252  -t utf-8 file

一部の文字セット(iso-8859-3、iso-8859-1など)には、多くの共通の文字があります-完全な文字セットを見つけたかどうかを確認するのは簡単ではありません...

したがって、メタデータを関連するテキスト(XMLなど)に関連付けることが非常に重要です。

2
JJoao
#!/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が意図されていると推測できます。だから私はそれをすべての既知のencodindgsで変換し、見つかるかどうかを調べます。

通常、適合するように見える複数のエンコーディングがあります。

長いファイルの場合は、数百ページを変換する代わりにスニペットをカットする場合があります。

だから私はそれを呼びます

encodingfinder.sh FILE Begrüßung

また、スクリプトテストでは、既知のエンコーディングで変換するかどうかに関係なく、「Begrüßung」を生成します。

ファンキーなキャラクターが目立つ場合が多いため、このようなキャラクターを見つけるには、通常はあまり役に立ちません。通常、文脈から、検索する適切な単語を推測できます。しかし、これをhexeditorで確認し、これが何バイトであるかを確認したくないので、エンコーディングの無限のテーブルにアクセスして、攻撃者を見つけます。 :)

0
user unknown