Neden bazı unicode karakterler terminalime yazdırılmıyor?


16

Adobe Source Code Pro yazı tipini kullanarak Arch Linux'u basit terminalle çalıştırıyorum. Yerel ayarım doğru olarak ayarlandı LANG=en_US.UTF-8.

Oyun kartlarını temsil eden Unicode karakterleri terminalime yazdırmak istiyorum. Referans için Wikipedia kullanıyorum .

Kart takımları için Unicode karakterler iyi çalışıyor. Örneğin,

$ printf "\u2660"

ekrana siyah bir kalp yazdırır.

Ancak, belirli oyun kartlarında sorun yaşıyorum. İhraç

$ printf "\u1F0A1"

Ἂ1maça ası yerine sembolü basar 🂡. Sorun ne?

Bu sorun birkaç terminalde (urxvt, xterm, termit) ve denediğim her yazı tipinde (DejaVu, Inconsolata) devam ediyor.


Uyarı: Bu, printf tarafından işleniyorsa, standart olmayan bir geliştirmedir. Yani böyle kaçışların hiç çalışmasını beklemeyin. Bakınız: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
— schily

Yanıtlar:


27

help printfprintf(1)yorumlanan kaçış dizileri için savunma yapar ve GNU printf için dokümanlar şunları söyler:

printf ISO C 99'da sunulan iki karakter sözdizimini yorumlar: \u dört onaltılık basamak hhhh olarak belirtilen 16 bit Unicode (ISO / IEC 10646) karakterler \Uiçin ve sekiz onaltılık basamak hhhhhhhh olarak belirtilen 32 bit Unicode karakterler için . yerel ayara printfgöre Unicode karakterleri LC_CTYPEçıkarır. U + 0000… U + 009F, U + D800… U + DFFF aralıklarındaki Unicode karakterler, U + 0024 ($), U + 0040 (@) ve U + 0060 (`) hariç, bu sözdizimi ile belirtilemez. .

ANSI C Alıntı için Bash kılavuzunda benzer bir şey belirtilmiştir ve echo:

\uHHHH
değeri onaltılık HHHH (bir ila dört onaltılık basamak) değeri olan Unicode (ISO / IEC 10646) karakteri

\UHHHHHHHH
değeri onaltılık HHHHHHHH (bir ila sekiz onaltılık basamak) değeri olan Unicode (ISO / IEC 10646) karakteri

Kısacası: \u5 onaltılık basamak için değildir. Bu \U:

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

2

Muru'nun cevabı tamamen doğrudur, ancak sadece bir noktayı açıklığa kavuşturmak için:

Yazdırırken \u1F0A1, bu on altı bitlik Unicode kaçış \u1F0Ave ardından değişmez karakter olarak yorumlanır 1(çünkü \uaşağıdaki dört karakteri alır, daha fazla, daha az değil). U + 1F0A daha sonra Ἂüzerinde birkaç aksan bulunan bir Yunan alfa verir ( Psili ve Varia ile Yunan Büyük Harf Alfa kesin ) verir.

Unicode kaçışınızda on altıdan fazla bit istiyorsanız, kullanmanız gerekir \U, bu sekiz karakterin altıgenini alır: \U0001F0A1size oyun kartı verecektir.


\U0001F0A1aslında daha taşınabilir \U1F0A1. Bu / dizileri printfilk kez tanıtan GNU bağımsız yardımcı programıdır ve için 4 basamak ve 8 için gerektirir . GNU kabuğunun yerleşimi, ksh93 ve zsh gibi diğer uygulamalar daha gevşektir. Her durumda POSIX değildir. Ancak POSIX, zsh değerlerini belirtecek ve 8 basamağın tümünü gerektirmeyecektir. \uXXXX\UXXXXXXXX\u\Uprintfprintf '\u/\U'$'\U1F0A1'
— Stéphane Chazelas

@ StéphaneChazelas İlginç, her zaman POSIX'in sekiz basamaklı biriyle gideceğini düşündüm. Koddan sonra ek harfler ve rakamlar yakalamaktan kaçınmak istiyorsanız, sekiz basamaklı sürümün hala zsh olarak geçerli olduğunu varsayıyorum?
— Draconis

Evet, \uxxxxbir yukarı 4 basamak ve \Uxxxxxxxxbir yukarı 8 basamak. Unicode'un artık 0 ile 0x10FFFF arasındaki kod noktaları (UTF16 tarafından getirilen bir sınırlama) ile sınırlı olduğunu unutmayın, bu nedenle kod noktalarında asla 6 basamaktan fazla olmayacaktır (yine \U123456789de 0x12345678 kod noktasının karakteri olarak yorumlanır 9ve başarısız olur). İçin POSIX belirtimi $'\u\U'hala tamamlanmadı (bkz. Austingroupbugs.net/view.php?id=249 ). Daha önceki bir taslakta, tüm 4/8 basamakları gerekiyordu, ancak bu daha sonra değişti (isteğim üzerine).
— Stéphane Chazelas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.