/ / Como posso remover caracteres não ASCII, mas deixar pontos e espaços usando Python? - python, texto, unicode, filtro, ascii

Como posso remover caracteres não-ASCII, mas deixar pontos e espaços usando Python? - python, texto, unicode, filtro, ascii

Eu estou trabalhando com um arquivo .txt. Eu quero uma seqüência de texto do arquivo sem caracteres não-ASCII. No entanto, eu quero deixar espaços e pontos. Actualmente, eu estou tirando aqueles também. Aqui está o código:

def onlyascii(char):
if ord(char) < 48 or ord(char) > 127: return ""
else: return char

def get_my_string(file_path):
f=open(file_path,"r")
data=f.read()
f.close()
filtered_data=filter(onlyascii, data)
filtered_data = filtered_data.lower()
return filtered_data

Como devo modificar o onlyascii () para deixar espaços e pontos? Eu imagino que não é muito complicado, mas eu não consigo descobrir.

Respostas:

129 para resposta № 1

Você pode filtrar todos os caracteres da string que não podem ser impressos usando string.printable, como isso:

>>> s = "somex00string. withx15 funny characters"
>>> import string
>>> printable = set(string.printable)
>>> filter(lambda x: x in printable, s)
"somestring. with funny characters"

string.printable na minha máquina contém:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
!"#$%&"()*+,-./:;<=>?@[\]^_`{|}~ tnrx0bx0c

56 para resposta № 2

Uma maneira fácil de mudar para um codec diferente é porusando encode () ou decode (). No seu caso, você deseja converter em ASCII e ignorar todos os símbolos que não são suportados. Por exemplo, a letra sueca å não é um caractere ASCII:

    >>>s = u"Good bye in Swedish is Hej dxe5"
>>>s = s.encode("ascii",errors="ignore")
>>>print s
Good bye in Swedish is Hej d

Editar:

Python3: str -> bytes -> str

>>>"Hej då".encode("ascii", errors="ignore").decode()
"hej d"

Python2: unicode -> str -> unicode

>>> u"hej då".encode("ascii", errors="ignore").decode()
u"hej d"

Python2: str -> unicode -> str (decodifica e codifica em ordem reversa)

>>> "hej dxe5".decode("ascii", errors="ignore").encode()
"hej d"

15 para resposta № 3

De acordo com o @artfulrobot, isso deve ser mais rápido que o filtro e o lambda:

re.sub(r"[^x00-x7f]",r"", your-non-ascii-string)

Veja mais exemplos aqui http://stackoverflow.com/questions/20078816/replace-non-ascii-characters-with-a-single-space/20079244#20079244


7 para resposta № 4

Sua pergunta é ambígua; Os dois primeirossentenças juntas implicam que você acredita que espaço e "período" são caracteres não-ASCII. Isso está incorreto. Todos os caracteres, de modo que ord (char) <= 127 são caracteres ASCII. Por exemplo, sua função exclui esses caracteres! "# $% &" () * +, -. / Mas inclui vários outros, por exemplo, [] {}.

Por favor, volte atrás, pense um pouco e edite o seupergunta para nos dizer o que você está tentando fazer, sem mencionar a palavra ASCII, e por que você acha que chars tais que ord (char)> = 128 são ignoráveis. Também: qual versão do Python? Qual é a codificação dos seus dados de entrada?

Por favor, note que o seu código lê toda a entradaarquivo como uma única seqüência de caracteres, e seu comentário ("ótima solução") para outra resposta implica que você não se importa com novas linhas em seus dados. Se o arquivo contiver duas linhas como esta:

this is line 1
this is line 2

o resultado seria "this is line 1this is line 2" ... É isso o que você realmente quer?

Uma solução maior incluiria:

  1. um nome melhor para a função de filtro do que onlyascii
  2. reconhecimento de que uma função de filtro precisa apenas retornar um valor geral se o argumento for mantido:

    def filter_func(char):
    return char == "n" or 32 <= ord(char) <= 126
    # and later:
    filtered_data = filter(filter_func, data).lower()
    

1 para resposta № 5

Se você quiser caracteres ASCII imprimíveis, provavelmente deverá corrigir seu código para:

if ord(char) < 32 or ord(char) > 126: return ""

isto é equivalente, para string.printable (resposta de @jterrace), exceto pela ausência de retornos e tabulações ("t", "n", "x0b", "x0c" e "r"), mas não corresponde ao intervalo da sua pergunta


0 para a resposta № 6

Trabalhando no meu caminho através do Fluent Python (Ramalho) - altamente recomendado. Listar um-ish-liners de compreensão inspirados no Capítulo 2:

onlyascii = "".join([s for s in data if ord(s) < 127])
onlymatch = "".join([s for s in data if s in
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"])