
작업 중인 파일에서 발견한 이상한 문자를 식별하려고 합니다.
$ 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진수 코드 포인트"는 ૫
잘못된 것 같다는 것을 알려줍니다 .
그렇다면 세 가지 옵션( 355
, 005353
또는 0aeb
) 중 하나를 사용하여 어떤 문자를 나타내야 하는지 알아내려면 어떻게 해야 합니까?
그리고 그렇습니다. 유니코드 도구를 사용해 보았지만 유효한 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
유니코드 U+FFFD 문자에 대한 설명을 이해하면 이는 실제 문자가 아니라 손상된 문자에 대한 자리 표시자입니다. 파일이 실제로 UTF-8로 인코딩되지 않았기 때문에 이는 의미가 있습니다.
답변1
파일에는 16진수로 EB와 0A라는 두 바이트가 포함되어 있습니다. 파일이 다음과 같이 문자당 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
로 줄여서8진수 덤프005353
2바이트는 8진수 단어이고, 16 진수 od -x
는 0aeb
단어이며, 파일의 실제 내용은 이 순서대로 2바이트 16진수 eb
입니다 .0a
따라서 005353
및 둘 다 0aeb
"16진수 코드 포인트"로 해석될 수 없습니다.
0a
LF(줄 바꿈)이며 eb
인코딩에 따라 다릅니다. file
단지 인코딩을 추측하는 것뿐입니다. 무엇이든 될 수 있습니다. 파일이 어디서 왔는지 등에 대한 추가 정보가 없으면 알아내기 어려울 것입니다.
답변3
텍스트 파일의 문자 집합을 100% 정확하게 추측하는 것은 불가능합니다.
다음과 같은 도구샤데,파이어폭스,파일 -i명시적인 문자 집합 정보가 정의되지 않은 경우(예: HTML의 머리 부분에 메타 문자 집합=...이 포함된 경우 상황이 더 쉽습니다) 텍스트가 충분히 크면 나쁘지 않은 경험적 방법을 사용하려고 합니다.
다음에서는 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"을 생성하는지 테스트합니다.
펑키한 캐릭터가 눈에 띄는 경우가 많기 때문에 그러한 캐릭터를 찾으려면 일반적으로 도움이 되지 않습니다. 일반적으로 문맥을 통해 검색할 올바른 단어를 유추할 수 있습니다. 그러나 우리는 이것이 어떤 바이트인지를 Hexeditor로 확인한 다음 끝없는 인코딩 테이블을 방문하여 위반자를 찾고 싶지 않습니다. :)