ASCII가 아닌 문자를 제거하고 Python을 사용하여 마침표와 공백을 남기려면 어떻게해야합니까?


100

.txt 파일로 작업하고 있습니다. ASCII가 아닌 문자가없는 파일의 텍스트 문자열을 원합니다. 그러나 공백과 마침표를 남기고 싶습니다. 현재 나는 그것들도 벗겨 내고있다. 코드는 다음과 같습니다.

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

공백과 마침표를 남기려면 onlyascii ()를 어떻게 수정해야합니까? 너무 복잡하지 않다고 생각하지만 이해할 수 없습니다.


설명 John에 대해 (진심으로) 감사합니다. 공백과 마침표가 ASCII 문자라는 것을 이해했습니다. 그러나 ASCII가 아닌 문자 만 제거하려고 시도하면서 의도하지 않게 두 가지를 모두 제거했습니다. 나는 내 질문이 그렇지 않다는 것을 어떻게 암시했는지 봅니다.

@PoliticalEconomist : 귀하의 문제는 여전히 매우 구체적이지 않습니다. 내 대답을 참조하십시오.
John Machin 2011

답변:


187

다음 과 같이 string.printable을 사용하여 인쇄 할 수없는 문자열의 모든 문자를 필터링 할 수 있습니다 .

>>> s = "some\x00string. with\x15 funny characters"
>>> import string
>>> printable = set(string.printable)
>>> filter(lambda x: x in printable, s)
'somestring. with funny characters'

내 컴퓨터의 string.printable에는 다음이 포함됩니다.

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

편집 : Python 3에서 필터는 iterable을 반환합니다. 문자열을 다시 얻는 올바른 방법은 다음과 같습니다.

''.join(filter(lambda x: x in printable, s))

2
서수 48 미만인 인쇄 가능한 문자는 어떻게됩니까?
joaquin

38
사용의 유일한 문제 filter는 iterable을 반환한다는 것입니다. 문자열이 다시 필요하면 (목록 압축을 할 때 필요했기 때문에 내가 한 것처럼) 다음을 수행하십시오 ''.join(filter(lambda x: x in string.printable, s)..
cjbarth

5
@cjbarth-주석은 파이썬 3에만 해당되지만 매우 유용합니다. 감사!
undershock

7
정규 표현식을 사용하지 않는 이유 : re.sub(r'[^\x00-\x7f]',r'', your-non-ascii-string). 이 스레드를 참조하십시오 stackoverflow.com/a/20079244/658497
노암 마 노스

1
@NoamManos 이것은 조인 ... 필터 ... lambda 솔루션, 감사합니다.
artfulrobot

95

다른 코덱으로 쉽게 변경하는 방법은 encode () 또는 decode ()를 사용하는 것입니다. 귀하의 경우 ASCII로 변환하고 지원되지 않는 모든 기호를 무시하려고합니다. 예를 들어 스웨덴 문자 å는 ASCII 문자가 아닙니다.

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

편집하다:

Python3 : str-> 바이트-> str

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

Python2 : 유니 코드-> str-> 유니 코드

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

Python2 : str-> unicode-> str (역순으로 디코딩 및 인코딩)

>>> "hej d\xe5".decode("ascii", errors="ignore").encode()
'hej d'

16
나는 얻는다UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 27
Xodarap777 2014 년

2
복사 붙여 넣기를 통해 문자열에 실제 유니 코드 문자를 넣을 때 오류가 발생했습니다. 문자열을 u'thestring '으로 지정하면 인코딩이 올바르게 작동합니다.
Ben Liyanage 2015

2
Py3에서만 작동하지만 우아합니다.
gaborous

7
@ Xodarap777과 동일한 오류가 발생하는 사람들을 위해 : 먼저 문자열을 .decode ()하고 인코딩 한 후에 만해야합니다. 예를 들어s.decode('utf-8').encode('ascii', errors='ignore')
Spc_555


6

귀하의 질문은 모호합니다. 처음 두 문장을 함께 사용하면 공백과 "마침표"가 ASCII가 아닌 문자라고 믿습니다. 이것은 올바르지 않습니다. ord (char) <= 127과 같은 모든 문자는 ASCII 문자입니다. 예를 들어, 함수는 이러한 문자! "# $ % & \ '() * +,-. /를 제외하지만 [] {}와 같은 다른 문자를 포함합니다.

뒤로 물러서서 조금 생각하고 ASCII라는 단어를 언급하지 않고 수행하려는 작업과 ord (char)> = 128과 같은 문자를 무시할 수 있다고 생각하는 이유를 알려주기 위해 질문을 편집하십시오. 또한 : 어떤 버전의 Python? 입력 데이터의 인코딩은 무엇입니까?

코드는 전체 입력 파일을 단일 문자열로 읽고 다른 답변에 대한 주석 ( "훌륭한 솔루션")은 데이터의 줄 바꿈에 대해 신경 쓰지 않는다는 것을 의미합니다. 파일에 다음과 같은 두 줄이있는 경우 :

this is line 1
this is line 2

결과는 'this is line 1this is line 2'... 그게 당신이 정말로 원하는 것입니까?

더 큰 솔루션은 다음과 같습니다.

  1. 필터 기능에 대한 더 나은 이름 onlyascii
  2. 인수가 유지되어야하는 경우 필터 함수가 진리 값을 반환해야한다는 것을 인식합니다.

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

이 답변은 OP와 비슷한 것을 묻기 위해 오는 우리에게 매우 유용하며 제안 된 답변은 유용하게 비단뱀입니다. 그러나 문제를 해석했을 때 문제에 대한 더 효율적인 해결책이 없다는 것이 이상합니다.
Xodarap777

5

다음 코드를 사용하여 영어가 아닌 문자를 제거 할 수 있습니다.

import re
str = "123456790 ABC#%? .(朱惠英)"
result = re.sub(r'[^\x00-\x7f]',r'', str)
print(result)

이것은 돌아올 것이다

123456790 ABC # %? . ()


1

인쇄 가능한 ASCII 문자를 원하는 경우 코드를 다음과 같이 수정해야합니다.

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

이것은 string.printable리턴과 탭 ( '\ t', '\ n', '\ x0b', '\ x0c'및 '\ r')이 없다는 점을 제외하면 (@jterrace의 답변)과 동일하지만 질문의 범위


1
약간 더 간단합니다 : lambda x : 32 <= ord (x) <= 126
jterrace

string.printable과 동일하지 않습니다. string.whitespace를 제외하기 때문입니다. OP가 원하는 것일 수 있지만 \ n 및 \ t와 같은 항목에 따라 다릅니다.
jterrace

@jterrace 오른쪽, 공백 (ord 32)을 포함하지만 반환 및 탭 없음
joaquin

예, "이것은 string.printable과 동일합니다"에 대해 주석을 달았지만 사실은 아닙니다
jterrace dec

답변을 수정했습니다. 감사합니다! OP 질문을주의 깊게 읽지 않으면 오해의 소지가 있습니다.
joaquin

1

Fluent Python (Ramalho)을 통해 작업하기-적극 권장합니다. 챕터 2에서 영감을 얻은 이해력 한 줄짜리 목록을 나열하십시오.

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

이것은 글 머리 기호,도 기호, 저작권 기호, 엔 기호 등과 같은 표준 ASCII 기호를 허용하지 않습니다. 또한 첫 번째 예에는 BELL과 같은 인쇄 할 수없는 기호가 포함되어있어 바람직하지 않습니다.
SherylHohman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.