Sayangnya, pengulangan string agak lambat di Python. Ekspresi reguler melebihi urutan besarnya lebih cepat untuk hal semacam ini. Anda hanya perlu membangun kelas karakter sendiri. The unicodedata modul cukup membantu untuk ini, terutama unicodedata.category () fungsi. Lihat Database Karakter Unicode untuk penjelasan tentang kategori.
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)
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)
Untuk Python2
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)
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)
Untuk beberapa kasus penggunaan, kategori tambahan (mis. Semua dari grup kontrol mungkin lebih disukai, meskipun ini mungkin memperlambat waktu pemrosesan dan meningkatkan penggunaan memori secara signifikan. Jumlah karakter per kategori:
Cc
(kontrol): 65
Cf
(format): 161
Cs
(pengganti): 2048
Co
(penggunaan pribadi): 137468
Cn
(belum digunakan): 836601
Edit Menambahkan saran dari komentar.
all_chars = (unichr(i) for i in xrange(sys.maxunicode))
untuk menghindari error build yang sempit.control_chars == '\x00-\x1f\x7f-\x9f'
(diuji pada Python 3.5.2)Sejauh yang saya tahu, metode paling pythonic / efisien adalah:
import string filtered_string = filter(lambda x: x in string.printable, myStr)
sumber
Anda dapat mencoba menyiapkan filter menggunakan
unicodedata.category()
fungsi:import unicodedata printable = {'Lu', 'Ll'} def filter_non_printable(str): return ''.join(c for c in str if unicodedata.category(c) in printable)
Lihat Tabel 4-9 di halaman 175 di properti karakter database Unicode untuk kategori yang tersedia
sumber
printable = {'Lu', 'Ll', Zs', 'Nd'}
Dengan Python 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})
Lihat postingan StackOverflow ini tentang menghapus tanda baca untuk mengetahui bagaimana .translate () dibandingkan dengan regex & .replace ()
Rentang dapat dibuat
nonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc')
menggunakan kategori basis data karakter Unicode seperti yang ditunjukkan oleh @Ants Aasma.sumber
text.translate({c:None for c in itertools.chain(range(0x00,0x20),range(0x7f,0xa0))})
.Berikut ini akan bekerja dengan masukan Unicode dan agak cepat ...
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('') == ''
Pengujian saya sendiri menunjukkan pendekatan ini lebih cepat daripada fungsi yang mengulang string dan mengembalikan hasil menggunakan
str.join
.sumber
LINE_BREAK_CHARACTERS = set(["\n", "\r"])
danand not chr(i) in LINE_BREAK_CHARACTERS
saat menyusun tabel.Fungsi ini menggunakan pemahaman daftar dan str.join, sehingga berjalan dalam waktu linier alih-alih O (n ^ 2):
from curses.ascii import isprint def printable(input): return ''.join(char for char in input if isprint(char))
sumber
filter(isprint,input)
Namun opsi lain di python 3:
re.sub(f'[^{re.escape(string.printable)}]', '', my_string)
sumber
r'[^' + re.escape(string.printable) + r']'
. (Saya rasa tidakre.escape()
sepenuhnya benar di sini, tetapi jika berhasil ...)Yang terbaik yang saya dapatkan sekarang adalah (terima kasih kepada python-izers di atas)
def filter_non_printable(str): return ''.join([c for c in str if ord(c) > 31 or ord(c) == 9])
Ini adalah satu-satunya cara saya mengetahui yang berfungsi dengan karakter / string Unicode
Ada pilihan yang lebih baik?
sumber
Yang di bawah ini bekerja lebih cepat dari yang lain di atas. Lihatlah
''.join([x if x in string.printable else '' for x in Str])
sumber
"".join([c if 0x21<=ord(c) and ord(c)<=0x7e else "" for c in ss])
Ada saat menggunakan
regex
perpustakaan: https://pypi.org/project/regex/Itu dipelihara dengan baik dan mendukung regex Unicode, Posix regex dan banyak lagi. Penggunaan (tanda tangan metode) sangat mirip dengan Python
re
.Dari dokumentasi:
(Saya tidak berafiliasi, hanya pengguna.)
sumber
Berdasarkan jawaban @ Ber, saya sarankan menghapus hanya karakter kontrol seperti yang didefinisikan dalam kategori database karakter Unicode :
import unicodedata def filter_non_printable(s): return ''.join(c for c in s if not unicodedata.category(c).startswith('C'))
sumber
startswith('C')
tetapi ini jauh kurang berkinerja dalam pengujian saya daripada solusi lainnya.if unicodedata.category(c)[0] != 'C'
sebagai gantinya. Apakah kinerjanya lebih baik? Jika Anda lebih suka kecepatan eksekusi daripada persyaratan memori, tabel dapat dihitung sebelumnya seperti yang ditunjukkan di stackoverflow.com/a/93029/3779655Untuk menghapus 'spasi',
import re t = """ \n\t<p> </p>\n\t<p> </p>\n\t<p> </p>\n\t<p> </p>\n\t<p> """ pat = re.compile(r'[\t\n]') print(pat.sub("", t))
sumber
Diadaptasi dari jawaban oleh Ants Aasma dan 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)
diuji pada Python 3.7.7
sumber