A iteração em strings é, infelizmente, bastante lenta em Python. As expressões regulares são mais do que uma ordem de magnitude mais rápidas para esse tipo de coisa. Você apenas tem que construir a classe de personagem sozinho. O módulo unicodedata é bastante útil para isso, especialmente a função unicodedata.category () . Consulte o banco de dados de caracteres Unicode para obter as descrições das categorias.
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)
Para 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)
# 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)
Para alguns casos de uso, categorias adicionais (por exemplo, todas do grupo de controle podem ser preferíveis, embora isso possa diminuir o tempo de processamento e aumentar o uso de memória significativamente. Número de caracteres por categoria:
Cc
(controle): 65
Cf
(formato): 161
Cs
(substituto): 2048
Co
(uso privado): 137468
Cn
(não atribuído): 836601
Editar Adicionando sugestões dos comentários.
all_chars = (unichr(i) for i in xrange(sys.maxunicode))
para evitar o erro de construção restrito.control_chars == '\x00-\x1f\x7f-\x9f'
(testado em Python 3.5.2)Pelo que eu sei, o método mais pitônico / eficiente seria:
fonte
Você pode tentar configurar um filtro usando a
unicodedata.category()
função:Consulte a Tabela 4-9 na página 175 nas propriedades de caracteres do banco de dados Unicode para as categorias disponíveis
fonte
printable = {'Lu', 'Ll', Zs', 'Nd'}
Em Python 3,
Veja esta postagem StackOverflow sobre como remover pontuação para saber como .translate () se compara a regex e .replace ()
Os intervalos podem ser gerados
nonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc')
usando as categorias do banco de dados de caracteres Unicode, conforme mostrado por @Ants Aasma.fonte
text.translate({c:None for c in itertools.chain(range(0x00,0x20),range(0x7f,0xa0))})
.O seguinte funcionará com entrada Unicode e é bastante rápido ...
Meus próprios testes sugerem que essa abordagem é mais rápida do que funções que iteram na string e retornam um resultado usando
str.join
.fonte
LINE_BREAK_CHARACTERS = set(["\n", "\r"])
eand not chr(i) in LINE_BREAK_CHARACTERS
ao construir a tabela.Esta função usa compreensões de lista e str.join, por isso é executado em tempo linear em vez de O (n ^ 2):
fonte
filter(isprint,input)
Mais uma opção em python 3:
fonte
r'[^' + re.escape(string.printable) + r']'
. (Eu não acho quere.escape()
esteja totalmente correto aqui, mas se funcionar ...)O melhor que descobri agora é (graças aos python-izers acima)
Esta é a única maneira que descobri que funciona com caracteres / strings Unicode
Alguma opção melhor?
fonte
O que está abaixo tem um desempenho mais rápido do que os outros acima. Dê uma olhada
fonte
"".join([c if 0x21<=ord(c) and ord(c)<=0x7e else "" for c in ss])
Existem ao usar a
regex
biblioteca: https://pypi.org/project/regex/É bem mantido e oferece suporte a Unicode regex, Posix regex e muitos mais. O uso (assinaturas de método) é muito semelhante ao do Python
re
.Da documentação:
(Não sou afiliado, apenas um usuário.)
fonte
Com base na resposta de @Ber, sugiro remover apenas os caracteres de controle, conforme definido nas categorias do banco de dados de caracteres Unicode :
fonte
Para remover 'espaços em branco',
fonte
Adaptado das respostas de Ants Aasma e shawnrad :
testado em Python 3.7.7
fonte