मेरे टर्मिनल पर कुछ यूनिकोड वर्ण प्रिंट क्यों नहीं होंगे?


16

मैं एडोब सोर्स कोड प्रो फ़ॉन्ट का उपयोग करके साधारण टर्मिनल के साथ आर्क लिनक्स चला रहा हूं। मेरा स्थान सही ढंग से सेट है LANG=en_US.UTF-8

मैं यूनिकोड के पात्रों को अपने टर्मिनल पर कार्ड खेलने का प्रतिनिधित्व करना चाहता हूं। मैं संदर्भ के लिए विकिपीडिया का उपयोग कर रहा हूँ ।

कार्ड सूट के लिए यूनिकोड के पात्र ठीक काम करते हैं। उदाहरण के लिए, जारी करना

$ printf "\u2660"

स्क्रीन पर एक काले दिल को छापता है।

हालाँकि, मुझे विशिष्ट प्लेइंग कार्ड्स से परेशानी हो रही है। जारी करने वाले

$ printf "\u1F0A1"

Ἂ1हुकुम a की बजाए प्रतीक को छापता है of। क्या गलत हो रहा है?

यह समस्या कई टर्मिनलों (urxvt, xterm, दीमक) और मेरे द्वारा आजमाए गए हर फॉन्ट (DejaVu, Inconsolata) पर बनी रहती है।


चेतावनी: यदि इसे प्रिंटफ द्वारा नियंत्रित किया जाता है, तो यह एक गैर-मानक वृद्धि है। इसलिए इस तरह के पलायन की उम्मीद बिल्कुल भी न करें। देखें: pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
schily

जवाबों:


27

help printfडिफेंस printf(1)सीक्वेंस की व्याख्या के लिए डिफर्स और जीएनयू प्रिंटफ के लिए डॉक्स कहते हैं:

printfव्याख्या दो चरित्र वाक्यविन्यास आईएसओ सी 99 में शुरू: \u16-बिट यूनिकोड (आईएसओ / आईईसी 10646) वर्ण, चार हेक्साडेसिमल अंक के रूप में निर्दिष्ट के लिए hhhh , और \U32-बिट यूनिकोड वर्ण, आठ हेक्साडेसिमल अंक के रूप में निर्दिष्ट के लिए hhhhhhhh । स्थान के printfअनुसार यूनिकोड वर्णों का आउटपुट देता है LC_CTYPE। यू + 0000… यू + 009 एफ, यू + डी 800… यू + डीएफएफएफ में यूनिकोड वर्ण यू + 0024 ($), यू + 0040 (@), और यू 0060 (`) को छोड़कर इस सिंटैक्स द्वारा निर्दिष्ट नहीं किए जा सकते हैं। ।

कुछ इसी तरह के लिए बैश के मैनुअल में निर्दिष्ट किया जाता है एएनएसआई सी का हवाला देते हुए और echo:

\uHHHH
यूनिकोड (ISO / IEC 10646) वर्ण जिसका मान हेक्साडेसिमल मान HHHH (एक से चार हेक्स अंक) है

\UHHHHHHHH
यूनिकोड (ISO / IEC 10646) वर्ण जिसका मान हेक्साडेसिमल मान HHHHHHHH (एक से आठ हेक्स अंक) है

संक्षेप में: \u5 हेक्स अंकों के लिए नहीं है। यह है \U:

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

2

मुरु का उत्तर पूरी तरह से सही है, लेकिन सिर्फ एक बिंदु को स्पष्ट करने के लिए:

जब आप प्रिंट कर रहे होते हैं \u1F0A1, तो इसकी व्याख्या सोलह-बिट यूनिकोड से बचकर की जाती है \u1F0A, उसके बाद शाब्दिक वर्ण 1(क्योंकि \uनिम्नलिखित चार अक्षर लगते हैं , अधिक नहीं, कम नहीं)। U + 1F0A तब देता है , इस पर एक ग्रीक अल्फ़ाज़ , जिसमें कुछ युगल डायकट्रिक्स हैं ( ग्रीक कैपिटल लेटर अल्फा विद साइली और वरिया , सटीक होना)।

यदि आप अपने यूनिकोड से बचने में सोलह से अधिक बिट्स चाहते हैं, तो आपको उपयोग करने की आवश्यकता है \U, जो कि हेक्स के आठ अक्षरों का मूल्य लेता है: \U0001F0A1आपको प्लेइंग कार्ड देगा।


\U0001F0A1की तुलना में वास्तव में अधिक पोर्टेबल है \U1F0A1। यह GNU स्टैंडअलोन printfउपयोगिता है जिसने पहले उन \uXXXX/ \UXXXXXXXXअनुक्रमों को पेश किया था और इसके लिए 4 अंक \uऔर 8 के लिए आवश्यकता होती है \U। अन्य printfकार्यान्वयन जैसे कि GNU शेल, ksh93 और zsh का निर्माण अधिक ढीला है। किसी भी मामले printf '\u/\U'में POSIX नहीं है। POSIX हालांकि zsh को निर्दिष्ट करने वाला है $'\U1F0A1'और सभी 8 अंकों की आवश्यकता नहीं होगी।
स्टीफन चेजलस

@ स्टेफेनचैलेजस दिलचस्प है, मुझे हमेशा लगा कि POSIX आठ अंकों के साथ जाएगा। यदि आप कोड के बाद अतिरिक्त अक्षरों और संख्याओं को कैप्चर करने से बचना चाहते हैं, तो मुझे लगता है कि आठ अंकों वाला संस्करण अभी भी zsh में मान्य है?
ड्रेकॉइस

हाँ, \uxxxxहै ऊपर 4 अंक के लिए और \Uxxxxxxxxहै ऊपर 8 अंक के लिए। ध्यान दें कि यूनिकोड अब कोडपॉइंट्स 0 से 0x10FFFF (UTF16 द्वारा लाया गया एक सीमा तक) तक सीमित है, इसलिए कोड पॉइंट्स में 6 से अधिक अंक कभी नहीं होंगे (फिर भी \U123456789कोड बिंदु 0x12345678 के चरित्र का अनुसरण किया जाएगा 9और असफल हो जाएगा)। $'\u\U'अभी भी POSIX विनिर्देश को अंतिम रूप नहीं दिया गया है (देखें austingroupbugs.net/view.php?id=249 )। पहले के मसौदे में, उन्हें सभी 4/8 अंकों की आवश्यकता थी लेकिन बाद में (मेरे अनुरोध पर) बदल गए।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.