如何识别一个奇怪的角色?


10

我试图识别我正在使用的文件中找到的一个奇怪字符:

$ 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“十六进制代码点” 似乎不正确,0aeb而“十六进制代码点” 又似乎是错误的。

所以,我怎么可以使用任何的三个选项(3550053530aeb)来找出他们应该代表什么人物?

是的,我确实尝试过使用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编码的,所以这很有意义。


5
EB在代码页437中为δ,在代码页850中为 ,,或者在8859-1中为 ë ;这些有道理吗?(iconv抱怨是因为您没有指定源字符集,所以它使用的默认值可能是UTF-8。)
Stephen Kitt

@StephenKitt是的,ë当在另一个程序上使用数据时,我看到的是!但是我怎么知道呢?它不是在我提供的数据中的某个地方吗?你是怎样找到它的?哦,我尝试过iconv-f ISO-8859但是它抱怨conversion from ISO-8859不被支持。
terdon

1
啊!我知道,我需要使用just eb并忽略0x十六进制指示符或其他内容。我对这种事情的无知是深刻的。您能否发布解释@StephenKitt的答案?
terdon

5
您此处的关键错误是ISO-8859不是编码的名称。这是一个编码家族;显然,您正在寻找的是ISO-8859-1。
Tripleee '17

1
这样,您iconv就可以成功了;和/或您可以在Wikipedia上查找它。对于这种非常特定的编码,fileformat.info / info / unicode / char / 00eb / index.htm也可以使用(Unicode相当于在128-255范围内的ISO-8859-1,尽管当然没有与之兼容的UTF编码) )。
3

Answers:


22

您的文件包含两个字节,EB和十六进制的0A。该文件使用的字符集可能每个字符一个字节,例如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 -xod -t x2一次读取两个字节的映射,在little-endian系统上以相反的顺序输出字节。

当您遇到这样的文件(不是有效的UTF-8文件(或解释为UTF-8文件没有意义))时,没有可靠的方法来自动确定其编码(和字符集)。上下文可以提供帮助:如果它是过去二十年来在西方PC上生成的文件,则很有可能会以ISO-8859-1,-15(欧元变体)或Windows-1252进行编码;如果比这更旧,则CP-437和CP-850可能是候选者。来自东欧系统,俄罗斯系统或亚洲系统的文件将使用我不太了解的不同字符集。然后是EBCDIC ...,iconv -l它将列出所有iconv已知的字符集,您可以从此处尝试并尝试。

(有一点我很了解CP-437和ATASCII,它们是日子。)


1
好的,在您链接到的Wikipedia页面上,我看到ë的描述为00EB234。这些额外的钱是00什么?为什么355不如我预期的那样od呢?我正在尝试获得有关如何使用od输出识别字符的更一般的答案。您能否解释一下有关十六进制代码的解释和/或需要什么信息才能识别未知字符(编码等)?
terdon

EB八进制数是353(不是355)。我会尝试概括一下...
Stephen Kitt

抱歉,我的意思是353。因此353是八进制表示形式,而不是十进制表示形式。啊
terdon

1
是的,“ o” od代表八进制;-)。
斯蒂芬·基特

1
无论如何,终端仿真器都将显示(U + FFFD),以代替在UTF-8中不能形成有效字符的0xeb字节。目前尚不清楚为什么uniprops $(cat file)(缺少引号的情况下)会报告(我不知道该uniprops命令)。unicode "$(cat file)"在Debian上确实输出Sequence '\xeb' is not valid in charset 'UTF-8'了我所期望的。
斯特凡Chazelas

5

请注意,od是短期的八进制转储,所以005353是两个字节为八进制字,od -x0aeb十六进制的话,你的文件的实际内容是两个字节eb,并0a以十六进制,在这个秩序。

因此,无论0053530aeb不能仅仅被理解为“十六进制代码点”。

0a是换行(LF),eb取决于您的编码。file只是猜测编码,可能是任何东西。如果没有任何其他信息,文件的来源等,将很难找到。


我意识到这是因为我不了解代码点(实际上是十六进制)是如何工作的,但是我怎么知道呢?我通常使用它,od -c因为这会产生我可以理解的输出。我如何使用355产生的那个来识别角色?为什么它打印0aeb代替eb0a,如果0a是换行?
terdon

@terdon endianness ...请参阅我的最新答案。
史蒂芬·基特

2

不可能以100%的准确度猜测文本文件的字符集。

当没有定义明确的字符集信息时,例如chardetfirefoxfile -i之类的工具(例如,如果HTML的头部包含meta charset = ...,事情就容易多了)将尝试使用启发式方法,如果文字足够大。

在下面的示例中,我将演示使用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)相关联非常重要。


嗯 我在这里无法复制它,它只是崩溃了。但是无论如何,这不是简单地告诉我文件的编码吗?我的问题是识别字符而不是文件的编码。我已经知道了
terdon

1
抱歉,我无法理解这个问题(我通常的问题是识别字符集)。如果您现在进行编码,iconv -f ... -t utf-8 会显示字符吗?
JJoao

不,我在那里显示编码。该编码不支持一个特定的字符,而我正在尝试识别该字符。
terdon

1
ISO-8859不是编码!编码为iso-8850-1。iso-8859是一个iso标准,它包括几个chaset定义。试试file -i ...
JJoao

1
@terdon,很抱歉坚持,但是,您尝试过的所有技巧都可以使用正确的字符集。例: iconv -f ISO-8859-1 -t UTF-8 file
JJoao

0
#!/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”。

要找到这样的角色,通常很少会有所帮助,因为时髦的角色经常脱颖而出。从上下文中,通常可以推断出要搜索的正确单词。但是我们不想与十六进制编辑器一起检查这是什么字节,然后访问无休止的编码表来查找我们的犯罪者。:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.