Unix字符集转换

Unix字符集转换

我对 Unix 中的字符集感到困惑。我通过 SFTP 下载了一个 CSV 文件:

$ file -ib myfile
text/plain; charset=us-ascii

此字符集任务的目的是文件中的数据看起来像:

Flyers: Video Center

虽然我想要:

Flyers: Video Center

我试过:

iconv -f us-ascii -t utf-8 myfile

这引发了以下错误:

iconv: illegal input sequence at position 528666

请澄清有关字符集的情况?通过 SFTP 获取文件时能否以 UTF-8 格式下载?我们通常如何确定字符集中什么是垃圾?

$Locale  
LANG=en_US.UTF-8  
LC_CTYPE="en_US.UTF-8"  
LC_NUMERIC="en_US.UTF-8"  
LC_TIME="en_US.UTF-8"  
LC_COLLATE="en_US.UTF-8"  
LC_MONETARY="en_US.UTF-8"  
LC_MESSAGES="en_US.UTF-8"  
LC_PAPER="en_US.UTF-8"  
LC_NAME="en_US.UTF-8"  
LC_ADDRESS="en_US.UTF-8"  
LC_TELEPHONE="en_US.UTF-8"  
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=  

$  LC_ALL=C sed -n l  
Zimbabwe,175,Unknown Network,-1,Unknown,-1,Unknown,-1,US: Flyers: Video Center:,854088,Standard Display,-998,10/28/2014

$ iconv -f utf-8 -t l1   
iconv: illegal input sequence at position 1228354  

当设置终端(在翻译下,字符集为 UTF-8)时,我能够看到干净的数据。
但是,当我使用 ETL 工具以 UTF-8 编码读取此内容时;数据被读取为垃圾。

当我 grep 文件中的数据时

"Flyers: Video Center" 

我没有看到数据存储为这一事实的结果

"Flyers: Video Center"

可以更改文件编码以便看到我想要的吗?

垃圾字符的十六进制转储:

0000000: 4e42 4353 3a20 4e48 4c2e 636f 6d3a 2055  NBCS: NHL.com: U  
0000010: 533a 2046 6c79 6572 733a c2a0 5669 6465  S: Flyers:..Vide  
0000020: 6fc2 a043 656e 7465 723a 2057 6861 7427  o..Center: What'  
0000030: 7320 486f 740a                           s Hot.  


$dd bs=1 skip=1228300 count=100 < temp1.csv | xxd  
100+0 records in  
100+0 records out  
100 bytes (100 B) copied, 0.000141 seconds, 709 kB/s  
0000000: 3031 342c 320a 556e 6b6e 6f77 6e20 436f  014,2.Unknown Co  
0000010: 756e 7472 792c 2d31 2c48 756c 7520 4c69  untry,-1,Hulu Li  
0000020: 7665 2c33 3738 3834 312c 4e42 433a 2041  ve,378841,NBC: A  
0000030: 6d65 7269 6361 e280 9973 2047 6f74 2054  merica...s Got T  
0000040: 616c 656e 743a 2053 686f 7274 666f 726d  alent: Shortform    
0000050: 2c33 3230 3631 3332 2c55 6e6b 6e6f 776e  ,3206132,Unknown  
0000060: 2053 6974                                 Sit  

一些乱码文本:

Junk Americaâs   

一定是(注意撇号不是 this ' but ')

America’s

BMW â Golden  

一定是(注意连字符是长连字符而不是这个 -):

BMW – Golden 

答案1

问题#1:grepping“Flyers:Video Center”...我没有看到结果

在文件的十六进制转储中,请注意字之间的两个字节 C2A0传单:视频。这是 UTF8 编码不间断空格grep NBSP 已知会失败欲了解更多信息,请阅读如何使用 sed 删除特殊的“M-BM-”字符使用 sed 替换 ...Hex c2a0。简短的回答是:

sed -i.bak -e 's/\xc2\xa0/ /' /path/to/file

问题#2“America's”显示为“Americaâs”(??):

这里,转储包含三个字节 e28099,称为右单引号(')。其实这里应该没有问题!您可能因上述问题而分心(您能确认吗?)

如果您使用grep,sed以及其他具有尊重您的语言环境(UTF8!)的表达式的工具,那么它将起作用:

printf 'America\xe2\x80\x99s\n' | grep --only-matching "[[:punct:]]"
printf 'America\xe2\x80\x99s\n' | sed -e "s/[[:punct:]]/?/"

如果你想摆脱所有那些UTF-8”特别的"字符,使用可以使用上面的提示或者iconv(不过现在已经很少有借口不支持UTF8了)。

删除所有非 ASCII 字符:

type a.txt | iconv -f utf8 -t ASCII//TRANSLIT

或者保留一种语言环境中的字符:

type a.txt | iconv -f utf8 -t iso8859-15//TRANSLIT | iconv -f iso8859-15 -t utf8

答案2

不像XML,它应该包含一个编码标签,描述您必须通过其他方式获取 csv 的该信息的原始内容编码。

尽管类型对于二进制数据效果很好,但对于文本数据则效果不佳。

这是由于命令的工作方式造成的。看男人的文字。粗略地:它查看前几个字节并尝试通过查找查找表中找到的内容来猜测内容。

因此,通常最好的做法是询问内容的创作者使用了哪种字符集。

如果这是不可能的——无论出于何种原因,图标是你在这里最好的朋友。

相关内容