2012-03-16 10 views
14

मैं कमांड लाइन पर पर्ल (या पायथन) का उपयोग कर utf8 को कैसे संभाल सकता हूं?कमांड लाइन पर utf8 को कैसे संभालें (पर्ल या पायथन का उपयोग करके)?

उदाहरण के लिए, मैं प्रत्येक शब्द में वर्णों को विभाजित करने की कोशिश कर रहा हूं। यह, गैर UTF8 पाठ के लिए बहुत आसान है, उदाहरण के लिए:

$ echo "abc def" | perl -ne 'my @letters = m/(.)/g; print "@letters\n"' | less 
a b c d e f 

लेकिन UTF8 के साथ, निश्चित रूप से काम नहीं करता है:

$ echo "одобрение за" | perl -ne 'my @letters = m/(.)/g; print "@letters\n"' | less 
<D0> <BE> <D0> <B4> <D0> <BE> <D0> <B1> <D1> <80> <D0> <B5> <D0> <BD> <D0> <B8> <D0> <B5> <D0> <B7> <D0> <B0> 

क्योंकि यह 2-बाइट के बारे में पता नहीं है वर्ण।

यह जानना भी अच्छा होगा कि यह कैसे (यानी, utf8 की कमांड लाइन प्रोसेसिंग) पाइथन में किया जाता है।

+0

'$ sed/s/./&/g '<<<" одбрение за "' ' और अधिक पढ़ें और –

+1

@ इग्नसियो वाज़्यूज़-एब्राम: 'sed' s /।/&/g''graphemes के लिए काम नहीं करता है (यह महत्वपूर्ण है कि किसी पाठ में संयुक्त वर्ण होते हैं, उदाहरण के लिए,' "Солженицын" ')। पर्ल में, पायथन इसे '/ \ X /' regex का उपयोग करके हल किया जा सकता है। – jfs

उत्तर

24

"-सी" झंडा पर्ल यूनिकोड में से कुछ को नियंत्रित करता है सुविधाओं (perldoc perlrun देखें):

$ echo "одобрение за" | perl -C -pe 's/.\K/ /g' 
о д о б р е н и е з а 

प्रयुक्त एन्कोडिंग निर्दिष्ट करने के लिए stdin/stdout के लिए आप PYTHONIOENCODING पर्यावरण चर का उपयोग कर सकते हैं:

$ echo "одобрение за" | PYTHONIOENCODING=utf-8 python -c'import sys 
for line in sys.stdin: 
    print " ".join(line.decode(sys.stdin.encoding)), 
' 
о д о б р е н и е з а 

आप पात्रों पर पाठ विभाजित करना चाहते हैं तो (ग्रफीम) सीमाओं (ऊपर कोड के रूप में कोड पॉइंट्स पर नहीं) तो आप /\X/ नियमित अभिव्यक्ति इस्तेमाल कर सकते हैं:

$ echo "одобрение за" | perl -C -pe 's/\X\K/ /g' 
о д о б р е н и е з а 

Grapheme Cluster Boundaries

देखें अजगर में \Xregex module द्वारा समर्थित है।

+1

+1 "Солженицын" व्यवहार करने के लिए +1! – DSM

+0

कूल, लेकिन '\ K' क्या है? – Frank

+0

@ फ्रैंक: ['\ K इसके सामान को छोड़ देता है]] (http://perldoc.perl.org/perlre.html# (% 3f% 3c% 3dpattern) -% 5cK) – jfs

4

मुझे पर्ल नहीं पता, इसलिए मैं पाइथन के लिए उत्तर दे रहा हूं।

पायथन को पता नहीं है कि इनपुट टेक्स्ट यूनिकोड में है। आपको यूनिकोड में यूटीएफ -8 या वास्तव में जो कुछ भी है, उससे स्पष्ट रूप से डीकोड करना होगा। फिर आप इसे संसाधित करने के लिए सामान्य पायथन टेक्स्ट प्रसंस्करण सामग्री का उपयोग कर सकते हैं।

http://docs.python.org/howto/unicode.html

यहाँ एक सरल पायथन 2.x कार्यक्रम आप की कोशिश करने के लिए है: मानक इनपुट से

import sys 

for line in sys.stdin: 
    u_line = unicode(line, encoding="utf-8") 
    for ch in u_line: 
     print ch, # print each character with a space after 

यह प्रतियां लाइनों, और यूनिकोड के लिए प्रत्येक पंक्ति बदल देता है। एन्कोडिंग को यूटीएफ -8 के रूप में निर्दिष्ट किया गया है। फिर for ch in u_line प्रत्येक चरित्र के लिए ch सेट करता है। फिर print ch, किसी चरित्र को मुद्रित करने के लिए पाइथन 2.x में आसान तरीका है, बिना किसी कैरिज रिटर्न के, एक स्पेस के बाद। अंत में एक नंगे print एक कैरिज रिटर्न जोड़ता है।

मैं अभी भी अपने अधिकांश काम के लिए पायथन 2.x का उपयोग करता हूं, लेकिन यूनिकोड के लिए मैं आपको पायथन 3.x का उपयोग करने की सलाह दूंगा। यूनिकोड सामान वास्तव में सुधार हुआ है।

उपरोक्त प्रोग्राम का पाइथन 3 संस्करण यहां है, जो मेरे लिनक्स कंप्यूटर पर परीक्षण किया गया है।

import sys 

assert(sys.stdin.encoding == 'UTF-8') 
for line in sys.stdin: 
    for ch in line: 
     print(ch, end=' ') # print each character with a space after 

डिफ़ॉल्ट रूप से, पायथन 3 मानता है कि इनपुट यूटीएफ -8 के रूप में एन्कोड किया गया है। डिफ़ॉल्ट रूप से, पाइथन फिर यूनिकोड में डीकोड करता है। पायथन 3 तार हमेशा यूनिकोड होते हैं; एक विशेष प्रकार bytes() एक स्ट्रिंग-जैसी ऑब्जेक्ट के लिए उपयोग किया जाता है जिसमें गैर-यूनिकोड मान ("बाइट्स") होते हैं। यह पायथन 2.x के विपरीत है; पायथन 2.x में, मूल स्ट्रिंग प्रकार बाइट्स की एक स्ट्रिंग थी, और यूनिकोड स्ट्रिंग एक विशेष नई चीज़ थी।

बेशक यह ज़रूरी नहीं है कि एन्कोडिंग यूटीएफ -8 है, लेकिन यह हमारे इरादों को दस्तावेज करने और यह सुनिश्चित करने का एक आसान तरीका है कि डिफ़ॉल्ट किसी भी तरह से नहीं बदला गया।

पायथन 3, print() में अब एक फ़ंक्शन है। और एक प्रिंट स्टेटमेंट के बाद एक कॉमा को जोड़ने के उस अजीब सिंटैक्स के बजाय इसे एक नई लाइन के बजाय एक जगह प्रिंट करने के लिए, अब एक नामित कीवर्ड तर्क है जो आपको अंत चार को बदलने देता है।

नोट: मूल रूप से पाइथन 2.x प्रोग्राम में इनपुट लाइन को संभालने के बाद, और पाइथन 3.x प्रोग्राम में print() को संभालने के बाद मेरे पास print कथन था। जैसा कि जेएफ सेबेस्टियन ने बताया, कोड इनपुट लाइन से वर्णों को प्रिंट कर रहा है, और अंतिम चरित्र एक नई लाइन होगी, इसलिए वास्तव में अतिरिक्त प्रिंट स्टेटमेंट की आवश्यकता नहीं है।

+0

पायथन 3.x यूनिकोड सामान वास्तव में बहुत कुछ नहीं बदला। केवल डिफ़ॉल्ट एन्कोडिंग, और कोड में अक्षर ही बदल गए हैं। इसके अलावा कुछ सामान का नाम बदल दिया गया है। इस संबंध में कोई नई कार्यक्षमता नहीं जोड़ा गया है। – nosklo

+0

@ नोस्को, जैसा कि मेरा दूसरा उदाहरण दिखाता है, डिफ़ॉल्ट अब यूनिकोड-पायथन 3.x में अवगत हैं। इनपुट स्ट्रिंग को यूनिकोड स्ट्रिंग में स्पष्ट रूप से रूपांतरित करने की आवश्यकता नहीं है; आप बस इसे संसाधित कर सकते हैं। यह आईएमएचओ में एक बहुत ही महत्वपूर्ण बदलाव है। – steveha

+0

पहले से ही एक नई लाइन है; आपको एक नंगे 'प्रिंट' कथन की आवश्यकता नहीं है, यानी 'प्रिंट' \ n ", 'नई लाइन को स्वयं ही प्रिंट करता है। – jfs

4
$ echo "одобрение за" | python -c 'import sys, codecs ; x = codecs. 
getreader("utf-8")(sys.stdin); print u", ".join(x.read().strip())' 
о, д, о, б, р, е, н, и, е, , з, а 

या आप यूनिकोड कोड पॉइंट्स चाहते हैं:

$ echo "одобрение за" | python -c 'import sys, codecs ; x = codecs. 
getreader("utf-8")(sys.stdin); print u", ".join("<%04x>" % ord(ch) 
for ch in x.read().strip())' 
<043e>, <0434>, <043e>, <0431>, <0440>, <0435>, <043d>, <0438>, 
<0435>, <0020>, <0437>, <0430> 
+1

यदि stdout रीडायरेक्ट किया गया है तो यह काम नहीं करेगा, उदाहरण के लिए, 'python -c ... | बिल्ली ' – jfs

5

"अरे", मैंने सोचा, "यह पर्ल में कितना मुश्किल हो सकता है?"

बाहर निकलना यह बहुत आसान है। दुर्भाग्यवश, यह पता लगाने से मुझे कितना समय लगा।

use utf8 पर एक त्वरित नज़र ने मुझे दिखाया कि यह अब अप्रचलित है। पर्ल की binmode आशाजनक लग रही थी, लेकिन काफी नहीं।

पाया गया Perluniintro है जो मुझे Perlunicode पर ले जाता है, जिसमें कहा गया है कि मुझे Perlrun पर देखना चाहिए। फिर, मैंने पाया कि मैं क्या देख रहा था।

पर्ल में कमांड लाइन स्विच -C है जो पर्ल से यूनिकोड स्विच करता है। हालांकि, -C कमांड लाइन स्विच के लिए कुछ विकल्प भी आवश्यक हैं। आपको यूनिकोड में क्या निर्दिष्ट करना है। एक convenient chart है जो आपको विभिन्न विकल्प दिखाता है। ऐसा लगता है कि perl -C स्वयं ही ठीक होगा। यह विभिन्न विकल्पों को जोड़ता है जो -CSDL या -C255 के बराबर है। हालांकि, इसका मतलब है कि यदि आपका LOCALE यूनिकोड पर सेट नहीं है, तो पर्ल यूनिकोड में काम नहीं करेगा।

इसके बजाय, आपको perl -CSD या -perl -C63 का उपयोग करना चाहिए।

$ echo "одобрение за" | perl -CSD -ne 'my @letters = m/(.)/g; print "@letters\n"' 
о д о б р е н и е з а 

युप, यह काम करता है।

आप केवल एक प्रश्न का उत्तर देने के बारे में कुछ सीख सकते हैं।

+1

+1: आपका मतलब हो सकता है '-CSDA' (' एआरजीवी' को संसाधित करने के लिए), हालांकि ओपी से लोकेल को 'utf-8'-आधारित माना जा सकता है, इसलिए केवल' -C' पर्याप्त है। – jfs

+2

यूटीएफ 8 का उपयोग बिल्कुल अप्रचलित नहीं है, यह सिर्फ इतना है कि इसका स्रोत कोड केवल यूआरएफ 8 में है। Utf8 में डेटा को निगलना और निकालने के लिए आपको अन्य चीजों को करने की आवश्यकता है। – Alex

+3

ठीक है, यूटीएफ 8 प्रगामा खत्म होने की तुलना में अधिक महत्वाकांक्षी रूप से शुरू हुई। यह कुछ ऐसी चीज के रूप में कल्पना की गई थी जो utf8 :: सभी की तरह होगी। –

संबंधित मुद्दे