পাইথনের একটি স্ট্রিং থেকে মুদ্রণযোগ্য অক্ষরগুলি কেটে ফেলা হচ্ছে


91

আমি চালাতে ব্যবহার করি

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

অনুলিপিযোগ্য অক্ষর থেকে পরিত্রাণ পেতে পার্ল অন করুন।

পাইথনে কোনও পসিক্স রেইগেক্স ক্লাস নেই, এবং আমি লিখতে পারি না [: মুদ্রণ:] এর অর্থ যা চাই আমি তা চাই। আমি পাইথনের কোনও উপায় জানি না যে কোনও অক্ষর মুদ্রণযোগ্য কিনা তা সনাক্ত করার জন্য।

আপনি কি করতে চান?

সম্পাদনা: এটি ইউনিকোড অক্ষরগুলিকেও সমর্থন করতে পারে। স্ট্রিং.প্রিন্টযোগ্য উপায় আনন্দের সাথে আউটপুট থেকে বের করে দেবে। অভিশাপ.এএসসিআই.আইসপ্রিন্ট কোনও ইউনিকোড চরিত্রের জন্য মিথ্যা ফিরিয়ে দেবে।

উত্তর:


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)

কিছু ব্যবহারের ক্ষেত্রে অতিরিক্ত বিভাগ (যেমন কন্ট্রোল গ্রুপ থেকে সমস্ত পছন্দনীয় হতে পারে, যদিও এটি প্রসেসিংয়ের সময়টি ধীর করতে পারে এবং মেমরির ব্যবহার উল্লেখযোগ্যভাবে বাড়িয়ে তুলতে পারে category প্রতি বিভাগে অক্ষরের সংখ্যা:

  • Cc (নিয়ন্ত্রণ): 65
  • Cf (ফর্ম্যাট): 161
  • Cs (সারোগেট): 2048
  • Co (ব্যক্তিগত ব্যবহার): 137468
  • Cn (স্বাক্ষরযুক্ত): 836601

মন্তব্যগুলি থেকে পরামর্শ যুক্ত করে সম্পাদনা করুন


4
এখানে কি 'সিসি' যথেষ্ট? আমি জানি না, আমি কেবল জিজ্ঞাসা করছি - আমার কাছে মনে হয় যে অন্যান্য 'সি' বিভাগগুলির মধ্যেও এই ফিল্টারটির প্রার্থী হতে পারে।
প্যাট্রিক জনমেয়ার

4
এই ফাংশনটি প্রকাশিত হিসাবে হিব্রু অক্ষরের অর্ধেকটি সরিয়ে দেয়। আমি প্রদত্ত দুটি পদ্ধতিতে একই প্রভাব পেয়েছি।
dotancohen

4
পারফরম্যান্সের দৃষ্টিকোণ থেকে, স্ট্রিং.টান্সলেট () এই ক্ষেত্রে দ্রুত কাজ করবে না? Stackoverflow.com/questions/265960/…
কাশ্যপ

4
all_chars = (unichr(i) for i in xrange(sys.maxunicode))সংকীর্ণ বিল্ড ত্রুটি এড়াতে ব্যবহার করুন ।
ডানমাইকেলহো

4
আমার জন্য control_chars == '\x00-\x1f\x7f-\x9f'(পাইথন 3.5.3.2 এ পরীক্ষিত)
এক্সো

74

আমি যতদূর জানি, সবচেয়ে পাইথোনিক / দক্ষ পদ্ধতিটি হ'ল:

import string

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

10
আপনি সম্ভবত ফিল্টারড স্ট্রিং = ''। জয়েন্ট (ফিল্টার (ল্যাম্বডা এক্স: স্ট্রিংয়ে প্রিন্টেবল, মাইএসটিআর)) চান যাতে আপনি একটি স্ট্রিং ফিরে পান
নাথান

12
দুঃখজনকভাবে স্ট্রিং.প্রিন্টেবল ইউনিকোড অক্ষর ধারণ করে না এবং এইভাবে ü বা the আউটপুটটিতে আসবে না ... সম্ভবত অন্য কিছু আছে?
ভিনকো ভার্সালোভিক

17
আপনি একটি তালিকা বোঝার বা জেনারেটর এক্সপ্রেশন ব্যবহার করা উচিত, ফিল্টার + ল্যাম্বদা নয়। এর মধ্যে একটি সময়ের 99.9% দ্রুততর হবে। '' .জাইন (মাইএসটিআর এর জন্য স্ট্রিং.প্রিন্টেবল হলে)
হাবনবিত

4
@ অ্যারোনগালাগার: ৯৯.৯% দ্রুত? কোথা থেকে আপনি এই চিত্রটি টানছেন? পারফরম্যান্স তুলনা যে খারাপ কাছাকাছি কোথাও নেই।
ক্রিস মরগান

4
হাই উইলিয়াম এই পদ্ধতিটি সমস্ত অ- ASCII অক্ষর মুছে ফেলা বলে মনে হচ্ছে। ইউনিকোডে অনেকগুলি ছাপার যোগ্য নন-এএসসিআইআই অক্ষর রয়েছে!
dotancohen

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

এটি নির্দেশ করার জন্য আপনাকে ধন্যবাদ। আমি সেই অনুযায়ী পোস্টটি সম্পাদনা করেছি
বের

4
এটি সর্বাধিক প্রত্যক্ষ, সোজা পদ্ধতি বলে মনে হচ্ছে। ধন্যবাদ
dotancohen

4
@ সিএসবাটো তিনটিই বৈধ এবং একই সেট ফলন করবে। আপনার সেটগুলি সম্ভবত একটি সেট আক্ষরিক নির্দিষ্ট করার সর্বোত্তম উপায়।
বের

4
@ আনুভব ঝালানি আপনি ফিল্টারটিতে আরও ইউনিকোড বিভাগ যুক্ত করতে পারেন। চিঠি ব্যবহারের সাথে ফাঁকা স্থান এবং অঙ্কগুলি সংরক্ষণ করার জন্যprintable = {'Lu', 'Ll', Zs', 'Nd'}
বার

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 () কীভাবে রেজেক্স এবং .replice () এর সাথে তুলনা করা যায় তার জন্য )

ইউনিকোড অক্ষর ডাটাবেস বিভাগnonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc') ব্যবহার করে রেঞ্জগুলি উত্পন্ন করা যেতে পারে @ আন্টস আসমা দ্বারা প্রদর্শিত।


ইউনিকোড ব্যাপ্তিগুলি ব্যবহার করা আরও ভাল হবে (@ আন্টার আসমার উত্তর দেখুন)। ফলাফল হবে 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


এটিই একমাত্র উত্তর যা ইউনিকোড চরিত্রগুলি নিয়ে আমার পক্ষে কাজ করে। আপনি পরীক্ষার কেস সরবরাহ করেছেন তা দুর্দান্ত!
পীর

4
আপনি লাইন ব্রেক জন্য অনুমতি চান, তাহলে যোগ 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))

4
filter(isprint,input)
ইঞ্চিতে

5

পাইথন 3 এ আরও একটি বিকল্প:

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

এটি আমার এবং এর 1 লাইনের জন্য দুর্দান্ত কাজ করেছে। ধন্যবাদ
লবালাগুন

4
কোনও কারণে এটি উইন্ডোজে দুর্দান্ত কাজ করে তবে এটি লিনাক্সে ব্যবহার করতে পারে না, আমাকে একটি আর এর জন্য চ পরিবর্তন করতে হয়েছিল তবে আমি নিশ্চিত নই যে এটিই সমাধান।
0-02 এ লবালাগুন চপ করুন

আপনার লিনাক্স পাইথনের মতো শব্দগুলি তখন এফ-স্ট্রিংগুলিকে সমর্থন করার জন্য অনেক পুরানো। আর-স্ট্রিংগুলি বেশ আলাদা, যদিও আপনি বলতে পারেন 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])

ইউনিকোডের অক্ষর / স্ট্রিংয়ের সাথে কাজ করে এমন একমাত্র উপায় found

আরও ভাল বিকল্প?


4
আপনি অজগর ২.৩ এ না থাকলে অভ্যন্তরীণ [] গুলি অপ্রয়োজনীয়। "ফিরুন '' .জায়েন (সি এর জন্য সি ...)"
হাবিবনেবিট

একেবারে অনর্থক নয় — এগুলির আলাদা অর্থ (এবং পারফরম্যান্সের বৈশিষ্ট্য) রয়েছে, যদিও শেষ ফলাফলটি একই।
মাইলস


7
তবে ইউনিকোড অক্ষর রয়েছে যা মুদ্রণযোগ্যও নয়।
ট্রিপলি


2

পাইথনে কোনও পসিক্স রেগেক্স ক্লাস নেই

ব্যবহার করার সময় আছে regexলাইব্রেরি : https://pypi.org/project/regex/

এটি ইউনিকোড রেজেক্স, পিক্সিক্স রেজেক্স এবং আরও অনেকগুলি ভালভাবে পরিচালনা করা হয় এবং সমর্থন করে। ব্যবহার (পদ্ধতি স্বাক্ষর) হয় খুব পাইথন এর অনুরূপ re

ডকুমেন্টেশন থেকে:

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

পসিক্স অক্ষর ক্লাসগুলি সমর্থিত। এগুলি সাধারণত একটি বিকল্প রূপ হিসাবে চিকিত্সা করা হয়\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')তবে এটি আমার পরীক্ষায় অন্য কোনও সমাধানের চেয়ে কম পারফর্মেন্ট ছিল।
বড় ম্যাকলার্জহিউজ

বড়-বিস্তৃতকরণ: আমার সমাধানের লক্ষ্যটি ছিল সম্পূর্ণতা এবং সরলতা / পঠনযোগ্যতার সংমিশ্রণ। if unicodedata.category(c)[0] != 'C'পরিবর্তে আপনি ব্যবহার করার চেষ্টা করতে পারেন । এটি আরও ভাল পারফর্ম করে? আপনি মেমরি প্রয়োজনীয়তা উপর সঞ্চালনের গতি পছন্দ করেন, এক টেবিলে প্রাক গনা করতে দেখানো stackoverflow.com/a/93029/3779655
darkdragon

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

করে উত্তর থেকে অভিযোজিত পিঁপড়া Aasma এবং shawnrad :

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)

পাইথন ৩.7..7 এ পরীক্ষা করা হয়েছে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.