अजगर में एक स्ट्रिंग से गैर मुद्रण योग्य अक्षर स्ट्रिपिंग


91

मैं चलाने के लिए उपयोग करता हूं

$s =~ s/[^[:print:]]//g;

गैर प्रिंट करने योग्य पात्रों से छुटकारा पाने के लिए पर्ल पर।

Python में POSIX regex कक्षाएं नहीं हैं, और मैं [: प्रिंट:] नहीं लिख सकता इसका मतलब यह है कि मुझे क्या चाहिए। मुझे पता है कि किसी चरित्र को छापने योग्य है या नहीं, इसका पता लगाने के लिए पायथन में कोई रास्ता नहीं है।

तुम क्या करोगे?

EDIT: इसे यूनिकोड वर्णों का भी समर्थन करना है। String.printable तरीका खुशी से उन्हें आउटपुट से बाहर कर देगा। शाप.सैसी.इस्प्रिंट किसी भी यूनिकोड वर्ण के लिए गलत वापस आ जाएगा।

जवाबों:


85

स्ट्रिंग्स पर इरेटिंग दुर्भाग्य से पायथन में धीमी है। इस तरह की चीज़ के लिए नियमित अभिव्यक्तियाँ तीव्रता के एक क्रम से अधिक होती हैं। आपको बस चरित्र वर्ग का निर्माण स्वयं करना है। Unicodedata मॉड्यूल इस के लिए काफी उपयोगी विशेष रूप से है, unicodedata.category () समारोह। श्रेणियों के विवरण के लिए यूनिकोड चरित्र डेटाबेस देखें ।

import unicodedata, re, itertools, sys

all_chars = (chr(i) for i in range(sys.maxunicode))
categories = {'Cc'}
control_chars = ''.join(c for c in all_chars if unicodedata.category(c) in categories)
# or equivalently and much more efficiently
control_chars = ''.join(map(chr, itertools.chain(range(0x00,0x20), range(0x7f,0xa0))))

control_char_re = re.compile('[%s]' % re.escape(control_chars))

def remove_control_chars(s):
    return control_char_re.sub('', s)

पायथन 2 के लिए

import unicodedata, re, sys

all_chars = (unichr(i) for i in xrange(sys.maxunicode))
categories = {'Cc'}
control_chars = ''.join(c for c in all_chars if unicodedata.category(c) in categories)
# or equivalently and much more efficiently
control_chars = ''.join(map(unichr, range(0x00,0x20) + range(0x7f,0xa0)))

control_char_re = re.compile('[%s]' % re.escape(control_chars))

def remove_control_chars(s):
    return control_char_re.sub('', s)

कुछ उपयोग-मामलों के लिए, अतिरिक्त श्रेणियां (उदाहरण के लिए नियंत्रण समूह से सभी बेहतर हो सकते हैं, हालांकि यह प्रसंस्करण समय को धीमा कर सकता है और स्मृति उपयोग को काफी बढ़ा सकता है। प्रति श्रेणी वर्णों की संख्या:

  • Cc (नियंत्रण): 65
  • Cf (प्रारूप): १६१
  • Cs (सरोगेट): 2048
  • Co (निजी-उपयोग): 137468
  • Cn (अप्रकाशित): 836601

टिप्पणियों से सुझाव जोड़ना संपादित करें


4
क्या 'Cc' यहाँ पर्याप्त है? मुझे नहीं पता, मैं सिर्फ यह पूछ रहा हूं - मुझे ऐसा लगता है कि अन्य 'सी' श्रेणियों में से कुछ इस फिल्टर के लिए भी उम्मीदवार हो सकते हैं।
पैट्रिक जॉनमेयर

1
यह फ़ंक्शन, जैसा कि प्रकाशित किया गया है, हिब्रू वर्णों में से आधे को हटा देता है। मैं दिए गए दोनों तरीकों के लिए समान प्रभाव प्राप्त करता हूं।
११:३२ पर

1
प्रदर्शन के दृष्टिकोण से, इस मामले में string.translate () तेजी से काम नहीं करेगा? देखें stackoverflow.com/questions/265960/…
कश्यप

3
all_chars = (unichr(i) for i in xrange(sys.maxunicode))संकीर्ण बिल्ड त्रुटि से बचने के लिए उपयोग करें ।
डेनमिकेलो

4
मेरे लिए control_chars == '\x00-\x1f\x7f-\x9f'(Python 3.5.2 पर परीक्षण किया गया)
AXO

73

जहाँ तक मुझे पता है, सबसे पायथोनिक / कुशल विधि होगी:

import string

filtered_string = filter(lambda x: x in string.printable, myStr)

10
आप शायद फ़िल्टर्ड_स्ट्रीमिंग = '' चाहते हैं। (जॉनी (फ़िल्टर लैम्ब्डा x: x in string.printable, myStr) ताकि आप एक स्ट्रिंग वापस पा सकें।
नाथन शाइली-सैंडर्स

12
अफसोस की बात है कि स्ट्रिंग में यूनिकोड वर्ण नहीं होते हैं, और इस प्रकार ü या ó आउटपुट में नहीं होगा ... शायद कुछ और है?
विन्को वेर्सालोविक

17
आपको एक सूची समझ या जनरेटर के भाव का उपयोग करना चाहिए, न कि फ़िल्टर + लैम्ब्डा। इनमें से एक 99.9% समय तेज होगा। '' .जॉइन (s for myStr अगर s में string.printable)
habnabit

3
@AaronGallagher: 99.9% तेजी से? किस जगह से आप उस आकृति को तोड़ते हैं? प्रदर्शन की तुलना उस बुरे के पास कहीं नहीं है।
क्रिस मॉर्गन

4
हाय विलियम। यह विधि सभी गैर- ASCII वर्णों को निकालने के लिए लगती है। यूनिकोड में कई मुद्रण योग्य गैर-एएससीआईआई अक्षर हैं!
11१२ डॉटनोहेन

17

आप unicodedata.category()फ़ंक्शन का उपयोग करके फ़िल्टर सेट करने का प्रयास कर सकते हैं :

import unicodedata
printable = {'Lu', 'Ll'}
def filter_non_printable(str):
  return ''.join(c for c in str if unicodedata.category(c) in printable)

उपलब्ध श्रेणियों के लिए यूनिकोड डेटाबेस चरित्र गुणों में पेज 175 पर तालिका 4-9 देखें


आपने एक सूची समझ शुरू की जो आपकी अंतिम पंक्ति में समाप्त नहीं हुई। मेरा सुझाव है कि आप उद्घाटन ब्रैकेट को पूरी तरह से हटा दें।
tzot

इस बारे में बताने के लिए शुक्रिया। मैंने तदनुसार पोस्ट संपादित किया
बेर

1
यह सबसे सीधा, सीधा तरीका लगता है। धन्यवाद।
dotancohen

1
@CabaToth तीनों वैध हैं और एक ही सेट प्राप्त करते हैं। आपका एक सेट शाब्दिक निर्दिष्ट करने का सबसे अच्छा तरीका है।
बेर

1
@AnubhavJhalani आप फ़िल्टर में अधिक यूनिकोड श्रेणियां जोड़ सकते हैं। अक्षरों का उपयोग करने के अलावा रिक्त स्थान और अंकों को आरक्षित करने के लिएprintable = {'Lu', 'Ll', Zs', 'Nd'}
Ber

11

पायथन 3 में,

def filter_nonprintable(text):
    import itertools
    # Use characters of control category
    nonprintable = itertools.chain(range(0x00,0x20),range(0x7f,0xa0))
    # Use translate to remove all non-printable characters
    return text.translate({character:None for character in nonprintable})

.Translate () की तुलना regex & .place () के लिए विराम-चिह्न हटाने पर इस StackOverflow पोस्ट को देखें।

पर्वतमाला यूनिकोड वर्ण डेटाबेस श्रेणियोंnonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc') का उपयोग करके उत्पन्न की जा सकती है जैसा कि @Ats Aasma द्वारा दिखाया गया है।


यूनिकोड पर्वतमाला (@Ants Aasma का उत्तर देखें) का उपयोग करना बेहतर होगा। परिणाम होगा text.translate({c:None for c in itertools.chain(range(0x00,0x20),range(0x7f,0xa0))})
डार्कड्रॉन

9

निम्नलिखित यूनिकोड इनपुट के साथ काम करेगा और बल्कि तेजी से ...

import sys

# build a table mapping all non-printable characters to None
NOPRINT_TRANS_TABLE = {
    i: None for i in range(0, sys.maxunicode + 1) if not chr(i).isprintable()
}

def make_printable(s):
    """Replace non-printable characters in a string."""

    # the translate method on str removes characters
    # that map to None from the string
    return s.translate(NOPRINT_TRANS_TABLE)


assert make_printable('Café') == 'Café'
assert make_printable('\x00\x11Hello') == 'Hello'
assert make_printable('') == ''

मेरा अपना परीक्षण बताता है कि यह दृष्टिकोण उन कार्यों की तुलना में तेज़ है जो स्ट्रिंग पर पुनरावृति करते हैं और परिणाम का उपयोग करके वापस आते हैं str.join


यह एकमात्र उत्तर है जो मेरे लिए यूनिकोड वर्णों के साथ काम करता है। बहुत बढ़िया है कि आपने परीक्षण मामले प्रदान किए!
पीर

1
यदि आप लाइन ब्रेक के लिए अनुमति देना चाहते हैं, तो तालिका बनाते समय जोड़ें LINE_BREAK_CHARACTERS = set(["\n", "\r"])और जोड़ें and not chr(i) in LINE_BREAK_CHARACTERS
पीर

5

यह फ़ंक्शन सूची बोध और str.join का उपयोग करता है, इसलिए यह O (n ^ 2) के बजाय रैखिक समय में चलता है:

from curses.ascii import isprint

def printable(input):
    return ''.join(char for char in input if isprint(char))

2
filter(isprint,input)
yingted

5

अजगर 3 में एक और विकल्प:

re.sub(f'[^{re.escape(string.printable)}]', '', my_string)

यह मेरे और इसकी 1 लाइन के लिए सुपर महान काम किया। धन्यवाद
चोप लालाबागुन

1
किसी कारण से यह विंडोज़ पर बहुत अच्छा काम करता है, लेकिन यह लिनक्स पर उपयोग नहीं कर सकता, मुझे आर के लिए एफ बदलना पड़ा लेकिन मुझे यकीन नहीं है कि यह समाधान है।
चोप लाबलगुन

तब आपके लिनक्स पायथन की तरह लगता है कि f- स्ट्रिंग्स का समर्थन करने के लिए बहुत पुराना था। आर-स्ट्रिंग्स काफी अलग हैं, हालांकि आप कह सकते हैं r'[^' + re.escape(string.printable) + r']'। (मुझे नहीं लगता कि re.escape()यहां पूरी तरह से सही है, लेकिन अगर यह काम करता है ...)
ट्रिपल

2

अब मैं सबसे अच्छा आया हूँ (ऊपर दिए गए अजगर के लिए धन्यवाद)

def filter_non_printable(str):
  return ''.join([c for c in str if ord(c) > 31 or ord(c) == 9])

यह एकमात्र तरीका है जो मुझे पता चला है कि यूनिकोड वर्ण / स्ट्रिंग्स के साथ काम करता है

कोई बेहतर विकल्प?


1
जब तक आप पाइथन 2.3 पर नहीं होते, तब तक आंतरिक [] निरर्थक होते हैं। "वापसी ''। जॉइन (c c ... के लिए)"
habnabit

बिल्कुल बेमानी नहीं हैं - उनके अलग-अलग अर्थ (और प्रदर्शन विशेषताएँ) हैं, हालांकि अंतिम परिणाम समान है।
मीलों

क्या सीमा के दूसरे छोर को भी संरक्षित नहीं किया जाना चाहिए ?: "ord (c) <= 126"
Gearoid मर्फी

7
लेकिन यूनिकोड वर्ण हैं जो प्रिंट करने योग्य नहीं हैं, भी।
ट्रिपलए

2

नीचे वाला ऊपर वाले की तुलना में तेजी से प्रदर्शन करता है। जरा देखो तो

''.join([x if x in string.printable else '' for x in Str])

"".join([c if 0x21<=ord(c) and ord(c)<=0x7e else "" for c in ss])
evandrix

2

Python में POSIX regex कक्षाएं नहीं हैं

regexपुस्तकालय का उपयोग करते समय: https://pypi.org/project/regex/

यह अच्छी तरह से बनाए रखा है और यूनिकोड regex, Posix regex और कई और अधिक का समर्थन करता है। उपयोग (विधि हस्ताक्षर) बहुत कुछ पायथन के समान है re

प्रलेखन से:

[[:alpha:]]; [[:^alpha:]]

POSIX वर्ण वर्ग समर्थित हैं। इन्हें आमतौर पर वैकल्पिक रूप में माना जाता है \p{...}

(मैं संबद्ध नहीं हूं, सिर्फ एक उपयोगकर्ता हूं।)


2

@ बेर के उत्तर के आधार पर, मेरा सुझाव है कि यूनिकोड वर्ण डेटाबेस श्रेणियों में परिभाषित केवल नियंत्रण वर्ण हटा दें :

import unicodedata
def filter_non_printable(s):
    return ''.join(c for c in s if not unicodedata.category(c).startswith('C'))

यह एक महान जवाब है!
tdc

आप कुछ के साथ हो सकते हैं, startswith('C')लेकिन यह मेरे परीक्षण में किसी अन्य समाधान की तुलना में बहुत कम था।
बजे बिग मैकलेरज्यूज

big-mclargehuge: मेरे समाधान का लक्ष्य पूर्णता और सरलता / पठनीयता का संयोजन था। आप if unicodedata.category(c)[0] != 'C'इसके बजाय उपयोग करने का प्रयास कर सकते हैं। क्या यह बेहतर प्रदर्शन करता है? यदि आप स्मृति आवश्यकताओं पर निष्पादन की गति पसंद करते हैं, तो एक तालिका को पूर्व-गणना कर सकते हैं जैसा कि stackoverflow.com/a/93029/3779655
डार्कड्रैगन

0

'व्हाट्सएप' को हटाने के लिए,

import re
t = """
\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>
"""
pat = re.compile(r'[\t\n]')
print(pat.sub("", t))

वास्तव में आपको तब वर्ग कोष्ठक की आवश्यकता नहीं होती है।
ट्रिपल

0

चींटियों के उत्तर से अनुकूलित आस्मा और शवनाद :

nonprintable = set(map(chr, list(range(0,32)) + list(range(127,160))))
ord_dict = {ord(character):None for character in nonprintable}
def filter_nonprintable(text):
    return text.translate(ord_dict)

#use
str = "this is my string"
str = filter_nonprintable(str)
print(str)

पायथन 3.7.7 पर परीक्षण किया गया

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.