का उपयोग 'utf8;' मुझे 'प्रिंट में व्यापक चरित्र' देता है


86

यदि मैं निम्नलिखित पर्ल कार्यक्रम चलाता हूं:

perl -e 'use utf8; print "鸡\n";'

मुझे यह चेतावनी मिली:

Wide character in print at -e line 1.

अगर मैं यह पर्ल प्रोग्राम चलाता हूं:

perl -e 'print "鸡\n";'

मुझे चेतावनी नहीं मिलती।

मैंने सोचा use utf8था कि एक पर्ल स्क्रिप्ट में UTF-8 वर्णों का उपयोग करना आवश्यक है। यह काम क्यों नहीं करता है और मैं इसे कैसे ठीक कर सकता हूं? मैं पर्ल 5.16.2 का उपयोग कर रहा हूं। मैं एक ही मुद्दा है अगर यह कमांड लाइन पर एक लाइनर होने के बजाय एक फ़ाइल में है।


3
"यह काम क्यों नहीं करता है?" यह काम करता है , लेकिन यह यूनिकोड के साथ मेरा अनुभव है कि वहाँ बहुत सारे टूटे हुए कार्यक्रम हैं जो यह देखते हैं कि वे काम कर रहे हैं। जब आप एक चीज को ठीक करते हैं, तो कोड को थोड़ा कम गलत बनाते हैं, तो परिणाम बहुत खराब लगते हैं। यह केवल तभी होता है जब आप अंतिम भाग को ठीक करते हैं कि सब कुछ फिर से अच्छा लगता है।
हॉब

जवाबों:


110

बिना use utf8पर्ल एकल बाइट पात्रों के अनुक्रम के रूप में आपकी स्ट्रिंग की व्याख्या करता है। आपकी स्ट्रिंग में चार बाइट्स हैं जैसा कि आप इससे देख सकते हैं:

$ perl -E 'say join ":", map { ord } split //, "鸡\n";'
233:184:161:10

पहले तीन बाइट्स आपके चरित्र को बनाते हैं, अंतिम एक लाइन-फीड है।

कॉल printइन चार वर्णों को STDOUT पर भेजता है। तब आपका कंसोल इन वर्णों को प्रदर्शित करने का तरीका बताता है। यदि आपका कंसोल UTF8 का उपयोग करने के लिए सेट है, तो यह उन तीन बाइट्स को आपके एकल वर्ण के रूप में व्याख्या करेगा और जो प्रदर्शित होता है।

यदि हम utf8मॉड्यूल में जोड़ते हैं, तो चीजें अलग होती हैं। इस मामले में, पर्ल आपके स्ट्रिंग की व्याख्या सिर्फ दो पात्रों के रूप में करता है।

$ perl -Mutf8 -E 'say join ":", map { ord } split //, "鸡\n";'
40481:10

डिफ़ॉल्ट रूप से, पर्ल की IO परत मानती है कि यह एकल-बाइट वर्णों के साथ काम कर रही है। इसलिए जब आप एक बहु-बाइट चरित्र को मुद्रित करने का प्रयास करते हैं, तो पर्ल सोचता है कि कुछ गलत है और आपको चेतावनी देता है। हमेशा की तरह, आप इस त्रुटि के लिए अधिक स्पष्टीकरण प्राप्त कर सकते हैं use diagnostics। यह कहेगा:

(एस utf8) पर्ल एक विस्तृत चरित्र (> 255) से मिला, जब वह उम्मीद नहीं कर रहा था। यह चेतावनी I / O (जैसे प्रिंट) के लिए डिफ़ॉल्ट रूप से है। इस चेतावनी को शांत करने का सबसे आसान तरीका है: आउटपुट में utf8 लेयर जोड़ना, जैसे कि बिनमोड STDOUT, ': utf8'। चेतावनी को बंद करने का एक और तरीका है कि कोई चेतावनी 'utf8' न जोड़ें; लेकिन वह अक्सर धोखा देने के करीब होता है। सामान्य तौर पर, आप एक एन्कोडिंग के साथ फाइलहैंडल को स्पष्ट रूप से चिह्नित करने वाले हैं, खुले और लंबवत / बिनमोड देखें।

जैसा कि दूसरों ने बताया है कि आपको पर्ल को मल्टी-बाइट आउटपुट स्वीकार करने की आवश्यकता है। ऐसा करने के कई तरीके हैं ( कुछ उदाहरणों के लिए पर्ल यूनिकोड ट्यूटोरियल देखें )। सबसे सरल तरीकों में से एक -CSकमांड लाइन ध्वज का उपयोग करना है - जो यूटीएफ 8 से निपटने के लिए तीन मानक फ़ाइलहैंडल (एसटीडीआईएन, एसटीडीयूएसटी और एसटीडीआरआर) बताता है।

$ perl -Mutf8 -e 'print "鸡\n";'
Wide character in print at -e line 1.
鸡

बनाम

$ perl -Mutf8 -CS -e 'print "鸡\n";'

यूनिकोड एक बड़ा और जटिल क्षेत्र है। जैसा कि आपने देखा है, कई सरल कार्यक्रम सही काम करते दिखाई देते हैं, लेकिन गलत कारणों से। जब आप कार्यक्रम का हिस्सा ठीक करना शुरू करते हैं, तो जब तक आप सभी कार्यक्रम तय नहीं कर लेते, तब तक चीजें अक्सर खराब हो जाएंगी ।


-Mutf8एक लाइनर पर्ल में नहीं तो वर्तनी कैसे करें ?
लेई यांग

@ लेय्यांग:use utf8;
डेव क्रॉस

80

सभी use utf8;को बताता है कि पर्ल कोड यूटीएफ -8 का उपयोग करके कूटबद्ध किया गया है। आपको यह बताने की आवश्यकता है कि पर्ल को अपने पाठ को कैसे एनकोड करना है:

use open ':std', ':encoding(UTF-8)';

धन्यवाद, यह कमांड लाइन पर वन-लाइनर्स के विपरीत फाइलों में संग्रहीत कार्यक्रमों के लिए अच्छी तरह से काम करता है, जो @ डेवक्रॉस के उत्तर को कवर करता है।
vktec

19

UTF-8 के रूप में सभी मानक आउटपुट को एनकोड करें:

binmode STDOUT, ":utf8";

2
use open ':std', ':encoding(UTF-8)';जैसा कि एक अन्य उत्तर द्वारा प्रस्तावित STDOUT के लिए है, लेकिन STDERR, और STDIN को UTF-8 के रूप में चिह्नित करता है, इसलिए आपको एक कथन की कीमत के लिए तीन मिलते हैं। यह भी देखें stackoverflow.com/a/42194059
स्टीफन ओस्टरमिलर

इस बात से सहमत। यह और भी बेहतर है।
बोरिस इवानोव

14

आप CPAN मॉड्यूल का उपयोग करके "बस हर जगह utf8 करें" के करीब पहुंच सकते हैं utf8::all

perl -Mutf8::all -e 'print "鸡\n";'

जब printकोई ऐसी चीज प्राप्त करता है जिसे वह मुद्रित नहीं कर सकता है (कोई :encodingपरत प्रदान किए जाने पर 255 से बड़ा वर्ण ), तो यह मान लेता है कि आप इसे UTF-8 का उपयोग कर सांकेतिक शब्दों में बदलना चाहते हैं। यह समस्या के बारे में चेतावनी देने के बाद ऐसा करता है।


5

आप इसका उपयोग कर सकते हैं,

perl -CS filename.

यह उस त्रुटि को भी समाप्त कर देगा।


केवल इसने मदद की
मुइलान

0

स्पैनिश में आप इस त्रुटि को पा सकते हैं जब उपयोग शुरू करने के बगल में:

use utf8;

आपका संपादक एन्कोडिंग एक अलग एन्कोडिंग में है। तो आप संपादक पर जो देखते हैं वह पर्ल नहीं करता है। उस त्रुटि को हल करने के लिए बस संपादक एन्कोडिंग को यूनिकोड / यूटीएफ -8 में बदलें ।


1
नहीं, यह वह नहीं है जो त्रुटि पैदा कर रहा था। कोड सब ठीक से UTF8 के रूप में कूटबद्ध किया गया था, लेकिन आउटपुट फ़ाइलहैंडल को पता नहीं था कि यह था।
डेव क्रॉस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.