
作業中のファイルで見つかった奇妙な文字を識別しようとしています。
$ 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バイトの文字セットを使用できます。ISO-8859-1; この文字セットでは、EB は ë です。
$ printf "\353\n" | iconv -f ISO-8859-1
ë
他の候補はδコードページ437, Ù inコードページ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ファイルとして解釈するときに意味のない)ファイルを見つけた場合、そのエンコード(および文字セット)を自動的に決定するための明確な方法はありません。コンテキストが役に立ちます。過去数十年にわたって西部のPCで生成されたファイルは、ISO-8859-1、-15(ヨーロッパのバリエーション)、またはWindows-1252でエンコードされている可能性があります。それより古い場合はCPです。 -437とCP-850が可能な候補だ。東ヨーロッパ、ロシア、アジアのファイルは、私が理解できない他の文字セットを使用します。その後、EBCDIC...はiconv -l
すべての既知の文字セットを一覧表示し、iconv
そこでいくつかの試行錯誤を実行できます。
(かつてCP-437とATASCIIを大部分覚えました。その時がそうでした。)
答え2
od
略語なので注意してくださいオクタルダンプ、005353
8進数の単語である2バイト、単語であるod -x
160aeb
進数、ファイルの実際の内容は、この順に2バイトeb
と16進数です。0a
したがって、005353
およびは0aeb
「16進コードポイント」として解釈することはできません。
0a
eb
エンコードによる改行文字(LF)。file
エンコーディングだけを推測すると、何でもすることができます。ファイルのソースなどの追加情報がなければ、見つけるのは難しいです。
答え3
テキストファイルの文字セットを100%正確に推測することは不可能です。
同様のツールシャダイ、Firefoxブラウザ、ファイル-i明確に定義された文字セット情報がない場合(たとえば、HTMLのヘッダーにメタ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
良い候補キャラクタセットを取得したら、ファイルキャラクタセットを「アクティブ」キャラクタセット(私の場合はutf-8)に変更するために使用するか、iconv
同様の方法を使用して正しく推測されるかどうかを確認できます。recode
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」を生成する既知のエンコーディングを使用して変換するかどうかをテストします。
このようなキャラクターを見つけるには、生意気なキャラクターが目立つ傾向があるため、少し少なく役立ちます。一般に、コンテキストを使用して検索する正しい単語を推論できます。しかし、我々はこれがどのバイトであるかを確認し、犯人を見つけるために無限のエンコーディングテーブルにアクセスするために16進エディタを使用したくありません。 :)