Chuyển đổi giữa các biểu mẫu chuẩn hóa Unicode trên dòng lệnh unix


22

Trong Unicode, một số kết hợp ký tự có nhiều hơn một đại diện.

Ví dụ, ký tự ä có thể được biểu diễn dưới dạng

  • "ä", đó là mật mã U + 00E4 (hai byte c3 a4trong mã hóa UTF-8) hoặc như
  • "ä", đó là hai điểm mã U + 0061 U + 0308 (ba byte 61 cc 88trong UTF-8).

Theo tiêu chuẩn Unicode, hai biểu diễn là tương đương nhưng trong các "hình thức chuẩn hóa" khác nhau, xem UAX # 15: Biểu mẫu chuẩn hóa Unicode .

Hộp công cụ unix có tất cả các loại công cụ chuyển đổi văn bản, sed , tr , iconv , Perl đến với tâm trí. Làm cách nào tôi có thể thực hiện chuyển đổi NF nhanh chóng và dễ dàng trên dòng lệnh?


2
Có vẻ như có một mô-đun "Unicode :: Bình thường hóa" cho perl, nên thực hiện loại việc này: search.cpan.org/~sadahiro/Unicode-N normalize -.16 / N normalize.pm
goldilocks

@goldilocks nếu nó có CLI thì ý tôi là, tôi có thể perl -MUnicode::Normalization -e 'print NFC(er er những gì đến đây bây giờ là
mirabilos

Câu trả lời:


20

Bạn có thể sử dụng uconvtiện ích từ ICU . Chuẩn hóa được thực hiện thông qua chuyển ngữ ( -x).

$ uconv -x any-nfd <<<ä | hd
00000000  61 cc 88 0a                                       |a...|
00000004
$ uconv -x any-nfc <<<ä | hd
00000000  c3 a4 0a                                          |...|
00000003

Trên Debian, Ubuntu và các dẫn xuất khác, uconvcó trong libicu-devgói. Trên Fedora, Red Hat và các công cụ phái sinh khác, và trong các cổng BSD, nó nằm trong icugói.


Điều này làm việc, cảm ơn. Bạn phải cài đặt một thư viện dev 30M cùng với nó. Tệ hơn nữa, tôi đã không thể tìm thấy tài liệu phù hợp cho chính uconv: bạn đã tìm thấy ở any-nfdđâu? Có vẻ như sự phát triển của công cụ này đã bị bỏ rơi, bản cập nhật cuối cùng là vào năm 2005.
glts

2
@glts Tôi tìm thấy any-nfdbằng cách duyệt qua danh sách được hiển thị bởi uconv -L.
Gilles 'SO- ngừng trở nên xấu xa'

Trên Ubuntu sử dụng sudo apt install icu-devtoolsđể chạy uconv -x any-nfc, nhưng không giải quyết được vấn đề đơn giản nhất , ví dụ: một bugText.txt tệp có "Iglésias, Bad-á, Good-á" được chuyển đổi bằng cách uconv -x any-nfc bugText.txt > goodText.txtgiữ nguyên văn bản.
Peter Krauss

7

Python có unicodedatamô-đun trong thư viện tiêu chuẩn của nó, cho phép dịch các biểu diễn Unicode thông qua unicodedata.normalize()chức năng:

import unicodedata

s1 = 'Spicy Jalape\u00f1o'
s2 = 'Spicy Jalapen\u0303o'

t1 = unicodedata.normalize('NFC', s1)
t2 = unicodedata.normalize('NFC', s2)
print(t1 == t2) 
print(ascii(t1)) 

t3 = unicodedata.normalize('NFD', s1)
t4 = unicodedata.normalize('NFD', s2)
print(t3 == t4)
print(ascii(t3))

Chạy với Python 3.x:

$ python3 test.py
True
'Spicy Jalape\xf1o'
True
'Spicy Jalapen\u0303o'

Python không phù hợp với lớp vỏ một lớp, nhưng nó có thể được thực hiện nếu bạn không muốn tạo tập lệnh bên ngoài:

$ python3 -c $'import unicodedata\nprint(unicodedata.normalize("NFC", "ääääää"))'
ääääää

Đối với Python 2.x, bạn phải thêm dòng mã hóa ( # -*- coding: utf-8 -*-) và đánh dấu các chuỗi là Unicode bằng ký tự u:

$ python -c $'# -*- coding: utf-8 -*-\nimport unicodedata\nprint(unicodedata.normalize("NFC", u"ääääää"))'
ääääää

3

Kiểm tra nó với hexdump công cụ:

echo  -e "ä\c" |hexdump -C 

00000000  61 cc 88                                          |a..|
00000003  

chuyển đổi với iconv và kiểm tra lại với hexdump:

echo -e "ä\c" | iconv -f UTF-8-MAC -t UTF-8 |hexdump -C

00000000  c3 a4                                             |..|
00000002

printf '\xc3\xa4'
ä

2
Điều này chỉ hoạt động trên macOS. Không có 'utf-8-mac' trên Linux, trên FreeBSD, v.v. Ngoài ra, việc phân tách bằng cách sử dụng mã hóa này không tuân theo đặc tả (mặc dù nó tuân theo thuật toán chuẩn hóa hệ thống tệp macOS). Thêm thông tin: search.cpan.org/~tomita/Encode-UTF8Mac-0.04/lib/Encode/
trộm

@antonone để công bằng mặc dù không có hệ điều hành được chỉ định trong câu hỏi.
roaima

1
@roaima Vâng, đó là lý do tại sao tôi cho rằng câu trả lời sẽ hoạt động trên tất cả các hệ thống dựa trên Unix / Linux. Câu trả lời trên chỉ hoạt động trên macOS. Nếu ai đó đang tìm kiếm một câu trả lời dành riêng cho macOS, thì nó sẽ hoạt động, một phần. Tôi chỉ muốn chỉ ra điều đó, bởi vì ngày khác tôi đã mất một thời gian để tự hỏi tại sao tôi không có utf-8-macLinux và liệu điều này có bình thường không.
antonone

3

Để hoàn thiện, với perl:

$ perl -CSA -MUnicode::Normalize=NFD -e 'print NFD($_) for @ARGV' $'\ue1' | uconv -x name
\N{LATIN SMALL LETTER A}\N{COMBINING ACUTE ACCENT}
$ perl -CSA -MUnicode::Normalize=NFC -e 'print NFC($_) for @ARGV' $'a\u301' | uconv -x name
\N{LATIN SMALL LETTER A WITH ACUTE}

2

coreutils có một bản vá để có được một thích hợp unorm. hoạt động tốt cho tôi trên wwars 4byte. theo dõi http://crashcference.housegordon.org/coreutils-multibyte-support.html#unorm Vấn đề còn lại có các hệ thống war 2 byte (cygwin, windows, cộng với aix và solaris trên 32 bit), cần chuyển đổi các điểm mã từ trên các mặt phẳng thành các cặp thay thế và ngược lại, và libunistring / gnulib cơ bản chưa thể xử lý được điều đó.

perl có unicharscông cụ, cũng thực hiện các hình thức chuẩn hóa khác nhau trên cmdline. http://search.cpan.org/dist/Unicode-Tussle/script/unichars


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.