Tại sao một số ký tự unicode in vào thiết bị đầu cuối của tôi?


16

Tôi đang chạy Arch Linux với thiết bị đầu cuối đơn giản sử dụng phông chữ Adobe Source Code Pro. Ngôn ngữ của tôi được đặt chính xác LANG=en_US.UTF-8.

Tôi muốn in các ký tự Unicode thể hiện các thẻ chơi đến thiết bị đầu cuối của mình. Tôi đang sử dụng Wikipedia để tham khảo .

Các ký tự Unicode cho phù hợp với thẻ hoạt động tốt. Ví dụ: ban hành

$ printf "\u2660"

in một trái tim màu đen lên màn hình.

Tuy nhiên, tôi gặp rắc rối với các thẻ chơi cụ thể. Phát hành

$ printf "\u1F0A1"

in biểu tượng Ἂ1thay vì ace of spades. Có chuyện gì thế?

Vấn đề này vẫn tồn tại trên một số thiết bị đầu cuối (urxvt, xterm, mối) và mọi phông chữ tôi đã thử (DejaVu, Inconsolata).


Cảnh báo: nếu điều này được xử lý bởi printf, thì đó là một cải tiến không chuẩn. Vì vậy, đừng mong đợi những lối thoát như vậy để làm việc. Xem: pubs.opengroup.org/onlinepub/9699919799/utilities/printf.html
schily

Câu trả lời:


27

help printftrì hoãn printf(1)các trình tự thoát được diễn giải và các tài liệu cho GNU printf nói:

printfdiễn giải hai cú pháp ký tự được giới thiệu trong ISO C 99: \ucho các ký tự Unicode 16 bit (ISO / IEC 10646), được chỉ định là bốn chữ số thập lục phân hhhh\Ucho các ký tự Unicode 32 bit, được chỉ định là tám chữ số thập lục phân hhhhhhhh . printfxuất các ký tự Unicode theo LC_CTYPEmiền địa phương. Các ký tự Unicode trong phạm vi U + 0000 Bằng U + 009F, U + D800 từ U + DFFF không thể được chỉ định theo cú pháp này, ngoại trừ U + 0024 ($), U + 0040 (@) và U + 0060 (`) .

Một cái gì đó tương tự được chỉ định trong hướng dẫn Bash cho Trích dẫn ANSI Cecho:

\uHHHH
ký tự Unicode (ISO / IEC 10646) có giá trị là giá trị thập lục phân HHHH (một đến bốn chữ số hex)

\UHHHHHHHH
ký tự Unicode (ISO / IEC 10646) có giá trị là giá trị thập lục phân HHHHHHHH (một đến tám chữ số hex)

Tóm lại: \ukhông dành cho 5 chữ số hex. Đó là \U:

# printf "\u2660 \u1F0A1 \U1F0A1\n"
 1 🂡

2

Câu trả lời của Muru là hoàn toàn chính xác, nhưng chỉ để làm rõ một điểm:

Khi bạn đang in \u1F0A1, điều đó được hiểu là một lối thoát Unicode mười sáu bit \u1F0A, theo sau là ký tự chữ 1(vì \ubốn ký tự sau, không hơn, không kém). U + 1F0A sau đó đưa ra , một alpha Hy Lạp với một vài dấu phụ trên đó ( chính xác là chữ Hy Lạp Alpha với Psili và Varia , chính xác).

Nếu bạn muốn có hơn mười sáu bit trong lối thoát Unicode của mình, bạn cần sử dụng \U, có giá trị hex của tám ký tự: \U0001F0A1sẽ cung cấp cho bạn thẻ chơi.


\U0001F0A1thực sự là di động hơn \U1F0A1. Đó là printftiện ích độc lập GNU lần đầu tiên giới thiệu những \uXXXX/ \UXXXXXXXXtrình tự đó và nó yêu cầu 4 chữ số cho \uvà 8 cho \U. Các printftriển khai khác như dựng sẵn của vỏ GNU, ksh93 và zsh thì lỏng lẻo hơn. Trong mọi trường hợp printf '\u/\U'không phải là POSIX. POSIX tuy nhiên sẽ chỉ định zsh's $'\U1F0A1'và sẽ không yêu cầu tất cả 8 chữ số.
Stéphane Chazelas

@ StéphaneChazelas Thú vị, tôi luôn nghĩ rằng POSIX sẽ đi với một chữ số tám chữ số. Tôi giả sử phiên bản tám chữ số vẫn còn hiệu lực trong zsh nếu bạn muốn tránh bắt thêm chữ và số sau mã?
Draconis

Vâng, \uxxxxlên đến 4 chữ số và \Uxxxxxxxxlên đến 8 chữ số. Lưu ý rằng Unicode hiện bị giới hạn ở các điểm mã 0 đến 0x10FFFF (giới hạn do UTF16 mang lại) nên các điểm mã sẽ không bao giờ có nhiều hơn 6 chữ số (vẫn \U123456789được hiểu là ký tự của điểm mã 0x12345678 theo sau 9và không thành công). Đặc tả POSIX cho $'\u\U'vẫn chưa được hoàn thiện (xem austingroupbugs.net/view.php?id=249 ). Trong một dự thảo trước đó, họ yêu cầu tất cả 4/8 chữ số nhưng điều đó đã thay đổi sau đó (theo yêu cầu của tôi).
Stéphane Chazelas
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.