मैं गैर-एएससीआईआई पात्रों को कैसे हटा सकता हूं लेकिन पायथन का उपयोग करके अवधि और रिक्त स्थान छोड़ सकता हूं?


100

मैं एक .txt फ़ाइल के साथ काम कर रहा हूँ। मुझे बिना गैर-ASCII वर्ण वाली फ़ाइल से पाठ की एक स्ट्रिंग चाहिए। हालांकि, मैं रिक्त स्थान और अवधि छोड़ना चाहता हूं। वर्तमान में, मैं उन लोगों को भी अलग कर रहा हूँ। यहाँ कोड है:

def onlyascii(char):
    if ord(char) < 48 or ord(char) > 127: return ''
    else: return char

def get_my_string(file_path):
    f=open(file_path,'r')
    data=f.read()
    f.close()
    filtered_data=filter(onlyascii, data)
    filtered_data = filtered_data.lower()
    return filtered_data

रिक्त स्थान और अवधियों को छोड़ने के लिए मुझे onlyascii () को कैसे संशोधित करना चाहिए? मुझे लगता है कि यह बहुत जटिल नहीं है, लेकिन मैं इसका पता नहीं लगा सकता।


धन्यवाद (ईमानदारी से) स्पष्टीकरण के लिए जॉन। मैं समझ गया कि रिक्त स्थान और अवधि ASCII वर्ण हैं। हालाँकि, मैं गैर-ASCII वर्णों को हटाने का प्रयास करते हुए दोनों को अनायास ही हटा रहा था। मैं देख रहा हूं कि मेरे सवाल का अन्यथा क्या प्रभाव पड़ सकता है।

@ पॉलिटिकल इकोनॉमिस्ट: आपकी समस्या अभी भी बहुत कम है। मेरा जवाब देखिए।
जॉन मैकिन

जवाबों:


187

आप स्ट्रिंग से सभी वर्णों को फ़िल्टर कर सकते हैं जो string.printable का उपयोग करके प्रिंट करने योग्य नहीं हैं , जैसे:

>>> s = "some\x00string. with\x15 funny characters"
>>> import string
>>> printable = set(string.printable)
>>> filter(lambda x: x in printable, s)
'somestring. with funny characters'

string.printable मेरी मशीन में शामिल हैं:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c

संपादित करें: पायथन 3 पर, फ़िल्टर एक पुनरावृत्त लौटाएगा। एक स्ट्रिंग वापस प्राप्त करने का सही तरीका होगा:

''.join(filter(lambda x: x in printable, s))

2
उन मुद्रण योग्य वर्णों के साथ क्या हो रहा है जो क्रमिक 48 से नीचे हैं?
जोकिन

38
उपयोग करने के साथ एकमात्र समस्या filterयह है कि यह एक पुनरावृत्ति देता है। यदि आपको वापस स्ट्रिंग की आवश्यकता है (जैसा कि मैंने किया था क्योंकि सूची संपीड़न करते समय मुझे इसकी आवश्यकता थी) तो ऐसा करें ''.join(filter(lambda x: x in string.printable, s):।
cjbarth

5
@cjbarth - टिप्पणी अजगर 3 विशिष्ट है, लेकिन बहुत उपयोगी है। धन्यवाद!
अंडर

7
नियमित अभिव्यक्ति का उपयोग क्यों न करें re.sub(r'[^\x00-\x7f]',r'', your-non-ascii-string):। इस सूत्र को देखें stackoverflow.com/a/20079244/658497
Noam Manos

1
@ नोमानमनोस यह मेरे लिए 4-5 गुना तेज था कि जॉइन ... फिल्टर ... लंबोदर सॉल्यूशन, थैंक्स।
Artfulrobot

95

एक अलग कोडेक में बदलने का एक आसान तरीका है, एनकोड () या डिकोड () का उपयोग करके। अपने मामले में, आप ASCII में कनवर्ट करना चाहते हैं और उन सभी प्रतीकों को अनदेखा करना चाहते हैं जो समर्थित नहीं हैं। उदाहरण के लिए, स्वीडिश पत्र å एक ASCII वर्ण नहीं है:

    >>>s = u'Good bye in Swedish is Hej d\xe5'
    >>>s = s.encode('ascii',errors='ignore')
    >>>print s
    Good bye in Swedish is Hej d

संपादित करें:

पायथन 3: str -> बाइट्स -> str

>>>"Hej då".encode("ascii", errors="ignore").decode()
'hej d'

पायथन 2: यूनिकोड -> स्ट्र -> यूनिकोड

>>> u"hej då".encode("ascii", errors="ignore").decode()
u'hej d'

पायथन 2: str -> यूनिकोड -> str (डिकोड और रिवर्स ऑर्डर में एनकोड)

>>> "hej d\xe5".decode("ascii", errors="ignore").encode()
'hej d'

16
मुझे मिलता हैUnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 27
Xodap777

2
मुझे वह त्रुटि मिली जब मैंने कॉपी पेस्ट के माध्यम से वास्तविक यूनिकोड चरित्र को स्ट्रिंग में डाल दिया। जब आप एक स्ट्रिंग निर्दिष्ट करते हैं तो u'thestring 'एनकोड सही ढंग से काम करता है।
बेन लीजैज

2
केवल Py3 पर काम करता है, लेकिन यह सुरुचिपूर्ण है।
जाबोन

7
उन लोगों के लिए जो @ Xodarap777 के समान त्रुटि प्राप्त कर रहे हैं: आपको सबसे पहले। उदाहरण के लिएs.decode('utf-8').encode('ascii', errors='ignore')
Spc_555

30

@Artfulrobot के अनुसार, यह फिल्टर और लैम्ब्डा से तेज होना चाहिए:

re.sub(r'[^\x00-\x7f]',r'', your-non-ascii-string) 

यहाँ और अधिक उदाहरण देखें http://stackoverflow.com/questions/20078816/replace-non-ascii-characters-with-a-single-space/20079244#20079244


1
यह समाधान ओपी के घोषित प्रश्न का उत्तर देता है, लेकिन सावधान रहें कि यह एएससीआईआई में शामिल गैर प्रिंट करने योग्य पात्रों को नहीं हटाएगा, जो मुझे लगता है कि ओपी से पूछना है।
डानिलो सूजा मोर्सज

6

आपका प्रश्न अस्पष्ट है; पहले दो वाक्यों को एक साथ लिए जाने का अर्थ है कि आप मानते हैं कि अंतरिक्ष और "अवधि" गैर-एएससीआईआई अक्षर हैं। यह गलत है। सभी वर्ण जैसे कि ord (char) <= 127 ASCII वर्ण हैं। उदाहरण के लिए, आपका फ़ंक्शन इन वर्णों को शामिल नहीं करता है! "# $% & \ '() * +, -। / लेकिन कई अन्य शामिल हैं जैसे [] {}।

कृपया वापस कदम बढ़ाएं, थोड़ा सोचें, और अपने प्रश्न को संपादित करके हमें बताएं कि आप क्या करने की कोशिश कर रहे हैं, एएससीआईआई शब्द का उल्लेख किए बिना, और आप यह क्यों सोचते हैं कि ऐसे वर्ण (वर्ण)> = 128 के अक्षर अज्ञानी हैं। इसके अलावा: पायथन का कौन सा संस्करण? आपके इनपुट डेटा की एन्कोडिंग क्या है?

कृपया ध्यान दें कि आपका कोड पूरी इनपुट फ़ाइल को एक स्ट्रिंग के रूप में पढ़ता है, और आपकी टिप्पणी ("महान समाधान") का एक और उत्तर देने का तात्पर्य है कि आप अपने डेटा में newlines के बारे में परवाह नहीं करते हैं। यदि आपकी फ़ाइल में इस तरह दो लाइनें हैं:

this is line 1
this is line 2

इसका परिणाम यह होगा 'this is line 1this is line 2'... कि क्या आप वास्तव में चाहते हैं?

एक बड़ा समाधान शामिल होगा:

  1. फिल्टर फ़ंक्शन के लिए एक बेहतर नाम से onlyascii
  2. मान्यता है कि यदि फ़िल्टर को बरकरार रखा जाना है तो फ़िल्टर फ़ंक्शन को एक सत्य मान वापस करना होगा:

    def filter_func(char):
        return char == '\n' or 32 <= ord(char) <= 126
    # and later:
    filtered_data = filter(filter_func, data).lower()

यह उत्तर हम में से उन लोगों के लिए बहुत मददगार है जो ओपी के समान कुछ पूछते हैं, और आपका प्रस्तावित उत्तर मददगार है। हालाँकि, मुझे यह अजीब लगता है कि समस्या का अधिक कुशल समाधान नहीं है क्योंकि आपने इसकी व्याख्या की है (जो कि मैं अक्सर चलाता हूं) - चरित्र द्वारा चरित्र, यह एक बहुत बड़ी फ़ाइल में बहुत लंबा समय लेता है।
Xodarap777

5

आप गैर-अंग्रेजी अक्षरों को हटाने के लिए निम्नलिखित कोड का उपयोग कर सकते हैं:

import re
str = "123456790 ABC#%? .(朱惠英)"
result = re.sub(r'[^\x00-\x7f]',r'', str)
print(result)

यह वापस आ जाएगी

123456790 ABC #%? । ()


1

यदि आप मुद्रण योग्य एएससीआई अक्षर चाहते हैं, तो आपको संभवतः अपना कोड सही करना चाहिए:

if ord(char) < 32 or ord(char) > 126: return ''

यह string.printableरिटर्न और टैब ('\ t', '\ n', '\ x0b', '\ x0c' और '\ r') की अनुपस्थिति को छोड़कर, (@jterrace से उत्तर) के बराबर है, लेकिन यह अनुरूप नहीं है अपने सवाल पर सीमा


1
थोड़ा सरल: लैम्ब्डा x: 32 <= ord (x) <= 126
jterrace

यह string.printable के समान नहीं है क्योंकि यह string.whitespace को छोड़ देता है, हालाँकि ऐसा हो सकता है जो OP चाहता है, \ n और \ t जैसी चीजों पर निर्भर करता है।
19

@ जेट्रेस राइट, में स्पेस (ऑर्ड 32) शामिल है, लेकिन कोई रिटर्न और टैब नहीं है
19

हाँ, सिर्फ "यह स्ट्रिंग के बराबर है" पर टिप्पणी करने योग्य है, लेकिन सच नहीं है
वाक्यविन्यास

मैंने उत्तर संपादित किया, धन्यवाद! यदि आप इसे ध्यान से नहीं पढ़ते हैं तो ओपी प्रश्न भ्रामक है।
जौनकिन

1

धाराप्रवाह पायथन (रामल्हो) के माध्यम से अपने तरीके से काम करना - अत्यधिक अनुशंसित। अध्याय 2 से प्रेरित एक-इश-लाइनर्स की सूची की समझ:

onlyascii = ''.join([s for s in data if ord(s) < 127])
onlymatch = ''.join([s for s in data if s in
              'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'])

यह मानक ASCII प्रतीकों के लिए अनुमति नहीं देगा, जैसे कि बुलेट अंक, डिग्री प्रतीक, कॉपीराइट प्रतीक, येन प्रतीक, आदि। इसके अलावा, आपके पहले उदाहरण में गैर-मुद्रण योग्य प्रतीक शामिल हैं, जैसे बीईएल, जो अवांछनीय है।
शेरिलहोमन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.