it-swarm-tr.com

Yazdırılamayan karakterleri python içindeki bir dizgiden çıkarma

Koşmak için kullanıyorum

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

basılabilir olmayan karakterlerden kurtulmak için Perl. 

Python'da POSIX regex sınıfı yoktur ve istediğim anlamını taşıyarak [: print:] yazamıyorum. Python'da bir karakterin yazdırılabilir olup olmadığını tespit etmenin bir yolu olmadığını biliyorum. 

Sen ne yapardın? 

EDIT: Unicode karakterleri de desteklemesi gerekiyor. String.printable yolu onları mutlu bir şekilde çıktıların dışına çıkarır. curses.ascii.isprint herhangi bir unicode karakter için false döndürecektir.

75
Vinko Vrsalovic

Python'da karakter dizileri üzerinde yineleme yapmak oldukça yavaş. Düzenli ifadeler, bu tür bir şey için daha hızlı bir büyüklük sırası bitti. Sadece karakter sınıfını kendin yapmalısın. Unicodedata modülü, özellikle unicodedata.category () işlevi için oldukça yararlıdır. Kategorilerin açıklamaları için Unicode Karakter Veritabanına bakınız.

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

Bildiğim kadarıyla, en Pythonic/verimli yöntem olacaktır:

import string

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

Python 3'te

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})

.Translate () ifadesinin regex & .replace () ile karşılaştırılması için bu noktalama işaretlerinin kaldırılmasıyla ilgili StackOverflow gönderisi bölümüne bakın.

9
shawnrad

unicodedata.category() işlevini kullanarak bir filtre ayarlamayı deneyebilirsiniz:

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

Mevcut kategoriler için Unicode veritabanı karakter özellikleri 'ye bakın.

8
Ber

Bu işlev liste kavramalarını ve str.join komutunu kullanır, bu nedenle O (n ^ 2) yerine doğrusal zamanda çalışır:

from curses.ascii import isprint

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

Şu ana kadar bulduğum en iyisi (yukarıdaki piton izleyiciler sayesinde) 

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

Unicode karakterleri/dizeleriyle çalıştığımı öğrendiğim tek yol bu.

Daha iyi bir seçenek var mı?

2
Vinko Vrsalovic

Python'da POSIX düzenli ifade sınıfı yoktur

regex kütüphanesini kullanırken var: https://pypi.org/project/regex/

İyi korunur ve Unicode regex, Posix regex ve daha pek çok şeyi destekler. Kullanım (yöntem imzaları), Python'un re öğesine benzer şekilde very şeklindedir.

Belgelerden:

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

POSIX karakter sınıfları desteklenir. Bunlar normalde \p{...} seçeneğinin alternatif bir şekli olarak ele alınır.

(Bağlı değilim, sadece bir kullanıcı.)

1
Risadinha

Aşağıdaki bir yukarıdaki diğerlerinden daha hızlı gerçekleştirir. Bir göz at

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

'Boşluk' kaldırmak için

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

python 3 içindeki bir başka seçenek:

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

Aşağıdaki Unicode girişi ile çalışacak ve oldukça hızlı ...

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('') == ''

Kendi testim, bu yaklaşımın string üzerinde yinelenen ve str.join kullanarak bir sonuç döndüren işlevlerden daha hızlı olduğunu gösteriyor.

0
ChrisP