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.