it-swarm-id.com

Mengupas karakter yang tidak dapat dicetak dari string dengan python

Saya gunakan untuk lari

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

pada Perl untuk menyingkirkan karakter yang tidak dapat dicetak. 

Dalam Python tidak ada kelas regex POSIX, dan saya tidak dapat menulis [: print:] memiliki arti yang saya inginkan. Saya tahu tidak ada cara dalam Python untuk mendeteksi apakah suatu karakter dapat dicetak atau tidak. 

Apa yang akan kamu lakukan? 

EDIT: Ini harus mendukung karakter Unicode juga. Cara string.printable akan dengan senang hati melepaskan mereka dari output. curses.ascii.isprint akan menghasilkan false untuk setiap karakter unicode.

75
Vinko Vrsalovic

Iterasi atas string sayangnya agak lambat di Python. Ekspresi reguler melebihi urutan besarnya lebih cepat untuk hal semacam ini. Anda hanya perlu membangun kelas karakter sendiri. Modul unicodedata cukup membantu untuk ini, terutama fungsi unicodedata.category (). Lihat Basis Data Karakter Unicode untuk deskripsi kategori.

import unicodedata, re

all_chars = (unichr(i) for i in xrange(0x110000))
control_chars = ''.join(c for c in all_chars if unicodedata.category(c) == 'Cc')
# or equivalently and much more efficiently
control_chars = ''.join(map(unichr, range(0,32) + range(127,160)))

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

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

Sejauh yang saya tahu, metode Pythonic/paling efisien adalah:

import string

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

Dalam Python 3,

def filter_nonprintable(text):
    import string
    # Get the difference of all ASCII characters from the set of printable characters
    nonprintable = set([chr(i) for i in range(128)]).difference(string.printable)
    # Use translate to remove all non-printable characters
    return text.translate({ord(character):None for character in nonprintable})

Lihat posting StackOverflow ini tentang menghapus tanda baca untuk bagaimana .translate () dibandingkan dengan regex & .replace ()

9
shawnrad

Anda dapat mencoba menyiapkan filter menggunakan fungsi unicodedata.category():

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

Lihat properti karakter basis data Unicode untuk kategori yang tersedia

8
Ber

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))
5
Kirk Strauser

Yang terbaik yang saya hasilkan 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 yang saya temukan yang berfungsi dengan karakter/string Unicode

Ada opsi yang lebih baik?

2
Vinko Vrsalovic

Dalam Python tidak ada kelas regex POSIX

Ada saat menggunakan perpustakaan regex: https://pypi.org/project/regex/

Itu terpelihara dengan baik dan mendukung Unicode regex, Posix regex dan banyak lagi. Penggunaan (tanda tangan metode) adalah sangat mirip dengan re Python.

Dari dokumentasi:

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

Kelas karakter POSIX didukung. Ini biasanya diperlakukan sebagai bentuk alternatif dari \p{...}.

(Saya tidak berafiliasi, hanya pengguna.)

1
Risadinha

Yang di bawah ini berkinerja lebih cepat daripada yang lain di atas. Lihatlah

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

Untuk menghapus 'spasi putih',

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
knowingpark

Berikut ini akan berfungsi dengan input 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 bahwa pendekatan ini lebih cepat daripada fungsi yang dilakukan di atas string dan mengembalikan hasil menggunakan str.join.

0
ChrisP