Làm thế nào tôi có thể xác định một nhân vật lạ?


10

Tôi đang cố gắng xác định một ký tự lạ mà tôi đã tìm thấy trong một tệp tôi đang làm việc với:

$ cat file
�
$ od file
0000000 005353
0000002
$ od -c file
0000000 353  \n
0000002
$ od -x file
0000000 0aeb
0000002

Tệp đang sử dụng mã hóa ISO-8859 và không thể chuyển đổi thành 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

Câu hỏi chính của tôi là làm thế nào tôi có thể giải thích đầu ra của odđây? Tôi đang cố gắng sử dụng trang này cho phép tôi dịch giữa các cách biểu thị ký tự khác nhau, nhưng nó cho tôi biết rằng 005353với tư cách là "điểm mã Hex" có vẻ không đúng và 0aebnhư "điểm mã Hex" , một lần nữa, có vẻ sai .

Vì vậy, làm thế nào tôi có thể sử dụng bất kỳ trong ba lựa chọn ( 355, 005353hoặc 0aeb) để tìm ra những nhân vật mà họ có nghĩa vụ phải đại diện?

Và vâng, tôi đã thử với các công cụ Unicode nhưng dường như đó cũng không phải là một ký tự UTF hợp lệ:

$ 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

nếu tôi hiểu mô tả về ký tự Unicode U + FFFD, thì đó hoàn toàn không phải là một ký tự mà là một trình giữ chỗ cho một ký tự bị hỏng. Điều này có ý nghĩa vì tệp không thực sự được mã hóa UTF-8.


5
EB có thể là δ trong trang mã 437 hoặc Ù ở trang mã 850 hoặc ë trong 8859-1 ; bất kỳ trong số đó có ý nghĩa? ( iconvphàn nàn vì bạn không chỉ định bộ ký tự nguồn, do đó, nó sử dụng mặc định của bạn có lẽ là UTF-8.)
Stephen Kitt

@StephenKitt vâng, ëlà những gì tôi thấy khi dữ liệu được sử dụng trên một chương trình khác! Nhưng làm thế nào tôi có thể biết điều này? Không phải nó ở đâu đó trong dữ liệu tôi cung cấp sao? Làm thế nào bạn tìm thấy nó? Ồ, tôi đã cố gắng iconvvới -f ISO-8859nhưng nó phàn nàn về conversion from tiêu chuẩn ISO-8859' không supported`.
terdon

1
Argh! Tôi thấy, tôi cần sử dụng chỉ ebvà bỏ qua 0xchỉ báo hex hoặc bất cứ điều gì đó là. Sự thiếu hiểu biết của tôi về loại điều này là sâu sắc. Bạn có thể gửi câu trả lời giải thích rằng @StephenKitt không?
terdon

5
Sai lầm nghiêm trọng của bạn ở đây là ISO-8859 không phải là tên của một mã hóa. Đó là một gia đình mã hóa; rõ ràng, thứ bạn đang tìm kiếm là ISO-8859-1.
tripleee

1
Sau đó, bạn iconvsẽ thành công; và / hoặc bạn có thể đã tra cứu nó, ví dụ như trên Wikipedia. Đối với mã hóa rất cụ thể này, fileformat.info/info/unicode/char/00eb/index.htm cũng hoạt động (Unicode tương đương với ISO-8859-1 trong phạm vi 128-255, mặc dù tất nhiên không có mã hóa UTF nào tương thích với nó ).
tripleee

Câu trả lời:


22

Tệp của bạn chứa hai byte, EB và 0A ở dạng hex. Có khả năng tệp đang sử dụng một bộ ký tự có một byte cho mỗi ký tự, chẳng hạn như ISO-8859-1 ; trong bộ ký tự đó, EB là ë:

$ printf "\353\n" | iconv -f ISO-8859-1
ë

Các ứng cử viên khác sẽ là δ trong mã trang 437 , Ù trong mã trang 850 ...

od -xĐầu ra là khó hiểu trong trường hợp này vì tính cuối cùng; một tùy chọn tốt hơn là -t x1sử dụng các byte đơn:

$ printf "\353\n" | od -t x1
0000000 eb 0a
0000002

od -xánh xạ tới od -t x2đó đọc hai byte cùng một lúc và trên các hệ thống cuối nhỏ xuất ra các byte theo thứ tự ngược lại.

Khi bạn gặp một tệp như thế này, không hợp lệ UTF-8 (hoặc vô nghĩa khi được hiểu là tệp UTF-8), không có cách nào để chứng minh tự động xác định mã hóa (và bộ ký tự). Bối cảnh có thể giúp: nếu đó là một tệp được tạo trên PC phương Tây trong vài thập kỷ qua, thì rất có thể nó được mã hóa theo ISO-8859-1, -15 (biến thể Euro) hoặc Windows-1252; nếu nó cũ hơn, CP-437 và CP-850 có thể là ứng cử viên. Các tệp từ các hệ thống Đông Âu, hoặc các hệ thống của Nga hoặc các hệ thống châu Á, sẽ sử dụng các bộ ký tự khác nhau mà tôi không biết nhiều. Sau đó, có EBCDIC ... iconv -lsẽ liệt kê tất cả các bộ ký tự iconvbiết và bạn có thể tiến hành thử nghiệm và sửa lỗi từ đó.

(Tại một thời điểm, tôi biết hầu hết CP-437 và ATASCII, đó là những ngày.)


1
OK, trong trang wikipedia mà bạn liên kết đến, tôi có thể thấy điều đó ëđược mô tả là 00EB234. Những gì thêm 00? Và tại sao nó không 355như tôi mong đợi từ odđầu ra? Tôi đang cố gắng để có được một câu trả lời tổng quát hơn về cách tôi có thể sử dụng odđầu ra để xác định nhân vật. Bạn có thể giải thích điều gì đó về việc diễn giải mã hex và / hoặc thông tin nào là cần thiết để có thể xác định một ký tự không xác định (mã hóa và bất cứ điều gì khác) không?
terdon

EB là 353 trong bát phân (không phải 355). Tôi sẽ cố gắng khái quát hóa ...
Stephen Kitt

Rất tiếc, ý tôi là vậy 353. Vì vậy, 353 là một đại diện bát phân, không phải là số thập phân. Argh.
terdon

1
Có, tiếng Nhật o odviết tắt của bát phân ;-).
Stephen Kitt

1
Trong mọi trường hợp, (U + FFFD) sẽ được trình giả lập đầu cuối hiển thị dưới dạng thay thế cho byte 0xeb đó không tạo thành ký tự hợp lệ trong UTF-8. Không rõ tại sao uniprops $(cat file)(thiếu trích dẫn btw) sẽ báo cáo rằng (tôi không biết về unipropslệnh đó ). unicode "$(cat file)"trên Debian không xuất ra Sequence '\xeb' is not valid in charset 'UTF-8'như tôi mong đợi.
Stéphane Chazelas

5

Lưu ý rằng odviết tắt của kết xuất bát phân , 005353hai byte là từ bát phân, od -x0aebdạng thập lục phân là từ và nội dung thực tế của tệp của bạn là hai byte eb0atheo hệ thập lục phân, theo thứ tự này.

Vì vậy, cả hai 0053530aebkhông thể được hiểu là "điểm mã hex".

0alà một nguồn cấp dữ liệu (LF) và ebphụ thuộc vào mã hóa của bạn. filechỉ là đoán mã hóa, nó có thể là bất cứ điều gì. Nếu không có thêm thông tin nơi tệp đến từ vv sẽ rất khó để tìm ra.


Tôi nhận ra điều này là do tôi không hiểu cách các điểm mã (hoặc hex, thực sự) hoạt động, nhưng làm thế nào tôi có thể biết điều này? Tôi thường sử dụng od -cvì điều đó tạo ra đầu ra tôi có thể hiểu. Làm thế nào tôi có thể sử dụng 355sản phẩm đó để xác định nhân vật? Và tại sao nó được in 0aebthay vì eb0anếu 0alà dòng mới?
terdon

@terdon endianness ... Xem câu trả lời cập nhật của tôi.
Stephen Kitt

2

Không thể đoán được với độ chính xác 100% bộ ký tự của các tệp văn bản.

Các công cụ như chardet , firefox , file -i khi không có thông tin bộ ký tự rõ ràng được xác định (ví dụ: nếu HTML chứa bộ ký tự meta = ... trong đầu, mọi thứ sẽ dễ dàng hơn) sẽ cố gắng sử dụng phương pháp phỏng đoán không quá tệ nếu văn bản đủ lớn

Sau đây, tôi chứng minh phát hiện bộ ký tự bằng chardet( pip install chardet/ apt-get install python-chardetnếu cần).

$ echo "in Noël" | iconv -f utf8 -t latin1  | chardet
<stdin>: windows-1252 with confidence 0.73

Sau khi ứng cử viên tốt charset, chúng ta có thể sử dụng iconv, recodehoặc tương tự để thay đổi các tập tin charset để charset "hoạt động" của bạn (trong trường hợp của tôi utf-8) và xem nếu nó đoán một cách chính xác ...

iconv -f windows-1252  -t utf-8 file

Một số bộ ký tự (như iso-8859-3, iso-8859-1) có nhiều ký tự chung - đôi khi không dễ để xem liệu chúng ta có tìm thấy bộ ký tự hoàn hảo ...

Vì vậy, rất quan trọng để có siêu dữ liệu được liên kết với văn bản có liên quan (ví dụ: XML).


Hừm. Tôi không thể tái tạo nó ở đây, nó chỉ bị hỏng. Nhưng trong mọi trường hợp, không phải chỉ đơn giản là cho tôi biết mã hóa của tập tin sao? Vấn đề của tôi là xác định ký tự không phải mã hóa của tệp. Điều đó tôi đã biết.
terdon

1
Xin lỗi, tôi không hiểu câu hỏi (vấn đề thông thường của tôi là xác định bộ ký tự). Nếu bây giờ bạn mã hóa, iconv -f ... -t utf-8 sẽ cho bạn thấy ký tự?
JJoao

Không. Tôi hiển thị mã hóa ngay tại đó. Có một nhân vật cụ thể không được hỗ trợ bởi mã hóa đó và đó là nhân vật mà tôi đang cố gắng xác định.
terdon

1
Iso-8859 không phải là mã hóa! mã hóa là iso-8850-1. iso-8859 là một iso nổi bật bao gồm một số định nghĩa chaset. Hãy thửfile -i ...
JJoao

1
@terdon, xin lỗi để nhấn mạnh, nhưng, tất cả các thủ thuật bạn đã thử làm việc với bộ ký tự đúng. Vd: 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 

Nếu tôi nhận được một tập tin, trong đó có Instance the Word Begrung, tôi có thể suy ra rằng Begrüßung có thể có nghĩa. Vì vậy, tôi chuyển đổi nó bằng tất cả các bộ mã hóa đã biết và xem xét, liệu có tìm thấy nó hay không, nó chuyển đổi nó đúng cách.

Thông thường, có nhiều bảng mã có vẻ phù hợp.

Đối với các tệp dài hơn, bạn có thể cắt một đoạn thay vì chuyển đổi hàng trăm trang.

Vì vậy, tôi sẽ gọi nó

encodingfinder.sh FILE Begrüßung

và các kịch bản kiểm tra, cho dù bằng cách chuyển đổi nó với các bảng mã đã biết, chúng tạo ra "Begrüßung".

Để tìm các nhân vật như vậy, thường ít giúp đỡ, vì các nhân vật sôi nổi thường nổi bật. Từ ngữ cảnh, từ đúng để tìm kiếm thường có thể được suy ra. Nhưng chúng tôi không muốn kiểm tra với một hexeditor, đây là byte nào, và sau đó truy cập các bảng mã hóa vô tận, để tìm ra kẻ phạm tội của chúng tôi. :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.