파일에 이상한 문자가 나타납니다

파일에 이상한 문자가 나타납니다

이상한 문자가 포함된 UTF-8 파일이 있습니다. 제 눈에는 다음과 같습니다.

<96>

이것이 어떻게 나타나는지vi

vi 스크린샷

그리고 그것이 어떻게 나타나는지gedit

gedit 스크린샷

LibreOffice에 표시되는 방식

리브레오피스 스크린샷

이로 인해 다음을 포함한 다양한 기본 Unix 도구에 문제가 발생합니다.

  1. cat file캐릭터를 사라지게 만들고 more,
  2. vi/vim에서 복사하여 붙여넣을 수 없습니다. 자체를 찾을 수도 없습니다.
  3. grep아무것도 표시할 수 없습니다. 마치 캐릭터가 존재하지 않는 것처럼 보입니다.

프로그램은 file잘 작동하며 UTF-8 파일로 인식합니다. 또한 파일의 특성상 웹상의 복사 및 붙여넣기에서 유래했을 가능성이 높으며 해당 문자는 원래 EMDASH를 의미한다는 것도 알고 있습니다.

내 기본 질문은 다음과 같습니다.

  1. 이 파일에 문제가 있나요?
  2. 동일한 파일에서 다른 항목을 어떻게 검색할 수 있나요?
  3. 동일한 문제/문자를 포함할 수 있는 다른 파일을 찾으려면 어떻게 해야 합니까?

문서는 여기에서 찾을 수 있습니다:파일.txt

답변1

파일에는 bytes 가 포함되어 있습니다 C2 96.UTF-8코드 포인트 U+0096의 인코딩. 이 코드 포인트는 다음 중 하나입니다.C1 제어 문자SPA "보호 지역 시작"(또는 "보호 지역")이라고도 합니다. 이는 현대 시스템에 유용한 문자는 아니지만, 그렇지 않을 가능성도 있습니다.해로운저기에있어.

원본 소스는 아마도 어딘가에서 잘못 트랜스코딩된 일부 단일 바이트 8비트 인코딩의 바이트 0x96일 것입니다. 아마 원래는 이랬을 거야.윈도우 CP1252대시 "-"는 해당 인코딩에서 바이트 값 96을 갖습니다. 대부분의 다른 가능한 후보는 위치 80-9F에 제어 세트를 가집니다. 이는 마치 latin-1인 것처럼 UTF-8로 변환되었습니다(ISO/IEC 8859-1) 이는 드문 일이 아닙니다. 그러면 보시다시피 바이트가 제어 문자로 해석되어 그에 따라 변환됩니다.


iconvglibc의 일부인 이 도구를 사용하여 이 파일을 복구 할 수 있습니다 .

iconv -f utf-8 -t iso-8859-1 < mwe.txt | iconv -f cp1252 -t utf-8

나를 위해 최소한의 예제의 올바른 버전을 생성하십시오. 먼저 UTF-8을 latin-1로 변환하고(이전의 잘못된 번역을 뒤집음) 재해석합니다.저것cp1252는 이를 다시 UTF-8로 올바르게 변환합니다.

그러나 이는 실제 파일에 무엇이 있는지에 따라 달라집니다. 다른 곳에 Latin-1 이외의 문자가 있으면 첫 번째 단계에서 해당 문자를 올바르게 인코딩할 수 없기 때문에 실패합니다.

iconv가 없거나 실제 파일에서 작동하지 않는 경우 sed를 사용하여 바이트를 바꿀 수 있습니다.

LC_ALL=C sed -e $'s/\xc2\x96/\xe2\x80\x93/g' < mwe.txt

C2 96이는 대시 인코딩을 UTF-8로 대체합니다 E2 80 93. 예를 들어 \xe2\x80\x93로 변경하여 하나 또는 두 개의 하이픈으로 바꿀 수도 있습니다 --.


비슷한 방법으로 grep을 수행할 수 있습니다. 사물을 해석하는 LC_ALL=C대신 실제 바이트를 읽고 있는지 확인하기 위해 사용하는 것 grep:

LC_ALL=C grep -R $'\xc2\x96` .

이 디렉토리에 있는 모든 바이트 항목이 나열됩니다. 콘텐츠가 혼합된 경우 바이너리 파일에는 바이트 쌍이 포함되는 경우가 많기 때문에 텍스트 파일로만 제한하고 싶을 수도 있습니다.

답변2

0x96은 Windows 코드 페이지 1252의 대시입니다. c2그 앞의 바이트는 이중 너비 문자의 기본 첫 번째 바이트인 것 같습니다. 다른 사람들이 더 정확하게 설명할 수 있습니다.

다른 항목을 검색하려면 명령 모드에서 해당 항목 위에 커서를 놓고 클릭 yl(문자 잡아당기기)한 다음 를 입력합니다 /<Ctrl>+r". (ctrl+r을 "사용하면 마지막으로 가져온 레지스터의 내용을 명령에 삽입할 수 있습니다.)

터미널에서 렌더링하려면 하이픈 두 개로 바꾸면 됩니다. 이것이 bibtex 파일이라면, 두 개의 하이픈을 입력하는 것이 적절한 방법입니다.

이 문자의 발생을 찾는 방법을 보여주기 위해 와 같은 16진수 덤프 도구를 통해 이를 수행할 수 있습니다 xxd.

$ cat tmp | xxd | grep c296
00000000: 7061 6765 733d 7b31 c296 3935 7d2c 0a70  pages={1..95},.p
00000020: 6765 733d 7b31 c296 3935 7d2c 0a70 6167  ges={1..95},.pag
00000040: 733d 7b31 c296 3935 7d2c 0a70 6167 6573  s={1..95},.pages
00000060: 7b31 c296 3935 7d2c 0a70 6167 6573 3d7b  {1..95},.pages={
00000080: c296 3935 7d2c 0a70 6167 6573 3d7b 31c2  ..95},.pages={1.
00000090: 9639 357d 2c0a 7061 6765 733d 7b31 c296  .95},.pages={1..
000000b0: 357d 2c0a 7061 6765 733d 7b31 c296 3935  5},.pages={1..95
000000d0: 2c0a 7061 6765 733d 7b31 c296 3935 7d2c  ,.pages={1..95},
000000f0: 7061 6765 733d 7b31 c296 3935 7d2c 0a70  pages={1..95},.p
00000110: 6765 733d 7b31 c296 3935 7d2c 0a70 6167  ges={1..95},.pag
00000130: 733d 7b31 c296 3935 7d2c 0a70 6167 6573  s={1..95},.pages
00000150: 7b31 c296 3935 7d2c 0a70 6167 6573 3d7b  {1..95},.pages={

답변3

파일의 텍스트는 입니다 pages = {1113},. 예, 숫자처럼 보이지만 1113실제로는 첫 번째 문자 뒤에 다른 문자가 있습니다 1. 예, 이 페이지의 편집 링크에서 문자열을 복사하여 붙여넣어 인코딩된 문자를 얻을 수 있습니다.

몇 가지 도구를 사용하여 문자열 내부를 살펴볼 수 있습니다.

$ a='pages = {1113},'

또는 명확하고 명확하게 만들고 편집 페이지를 사용하지 않고도 쉽게 복사하여 붙여넣을 수 있도록 하려면 다음을 수행하세요.

$ a=$(printf 'pages = {1\xc2\x96113},') 

$ echo "$a" | od -An -tx1c
  70  61  67  65  73  20  3d  20  7b  31  c2  96  31  31  33  7d
   p   a   g   e   s       =       {   1 302 226   1   1   3   }
  2c  0a
   ,  \n

$ echo "$a" | sed -n l
pages = {1\302\226113},$

$ echo "$a" | xxd
00000000: 7061 6765 7320 3d20 7b31 c296 3131 337d  pages = {1..113}
00000010: 2c0a

따라서 문자는 2바이트 값 c2 96(hex) 또는 302 226(octal)입니다.
UTF-8로 인코딩된 바이트 값 96이거나 유니코드 문자로 표시 될 수 있습니다 U-0096.

값(현재 UTF-8 또는 ISO-8859-1이 더 좋음)은 C1 영역의 제어 문자입니다(위키피디아 페이지) 그리고(유니코드 PDF), 128부터 159까지의 십진수. 구체적으로 U-0096은 "격리 구역 시작" 또는온천.

이 값(dec 150)은 ASCII 범위(0-127)를 벗어나며 (이전에는) 사용된 코드 페이지에 따라 여러 문자를 나타내는 데 사용되었습니다. 이전에는 Windows-1252에서 인코딩된 대시(1-113 범위를 표시하는 데 사용됨)였다고 가정하는 것이 합리적입니다(마이크로소프트 페이지) (위키피디아 1252)라고 불린다.대시(이것은 두 개의 대시 중 더 작은 것입니다.zh그리고) (위키피디아와 대시) 또는 구어체로 대시( -)를 사용합니다.


Q1: 이 파일에 문제가 있나요?

제어 문자는 유효한 문자이며 거의 사용되지 않지만 여전히 유효합니다.

그러나 편집을 더 쉽게 하기 위해 대시로 바꿀 수 있습니다.

<file.txt sed 's/\xc2\x96/-/'

Q2 - 동일한 파일에서 다른 항목을 검색하는 방법은 무엇입니까?

sed -n '/\xc2\x96/p'             # will print lines that contain that character.

또는 grep을 사용하여 문자를 검색하고(문자는 인쇄할 수 없으므로 색상 강조 표시가 표시되지 않음) 행을 인쇄할 수 있습니다.

c="$(printf "\U96")" ; grep "$c" file.txt

또는 더 광범위하게는 해당 제어 문자 범위 내의 모든 문자를 찾고 해당 문자가 포함된 파일을 나열합니다.

grep -rlP "[\x80-\x9f]"    

Q3 - 동일한 문제/문자를 포함할 수 있는 다른 파일을 찾으려면 어떻게 해야 합니까?

해당 문자와 ​​일치하는 ( ) 파일이 나열됩니다 -l.

grep -rlP "\x96"

관련 정보