[python] 파이썬의 문자열에서 인쇄 할 수없는 문자 제거

나는 달리는 데 사용

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

Perl에서 인쇄 할 수없는 문자를 제거합니다.

파이썬에는 POSIX 정규식 클래스가 없으며 내가 원하는 것을 의미하는 [: print :]를 작성할 수 없습니다. 나는 파이썬에서 문자가 인쇄 가능한지 아닌지를 감지하는 방법을 모른다.

당신은 무엇을 하시겠습니까?

편집 : 유니 코드 문자도 지원해야합니다. string.printable 방법은 출력에서 ​​행복하게 제거합니다. curses.ascii.isprint는 모든 유니 코드 문자에 대해 false를 반환합니다.



답변

불행히도 파이썬에서는 문자열을 반복하는 것이 다소 느립니다. 정규 표현식은 이런 종류의 일보다 훨씬 더 빠릅니다. 캐릭터 클래스를 직접 구축하면됩니다. 한편 UnicodeData 모듈은 특히이에 매우 도움이된다 unicodedata.category () 함수입니다. 범주에 대한 설명은 유니 코드 문자 데이터베이스 를 참조하십시오 .

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)

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)

일부 사용 사례의 경우 추가 범주 (예 : 제어 그룹의 모든 범주 가 더 바람직 할 수 있지만 처리 시간이 느려지고 메모리 사용량이 크게 증가 할 수 있습니다. 범주 당 문자 수 :

  • Cc (대조군) : 65
  • Cf (형식) : 161
  • Cs (대리) : 2048
  • Co (개인용) : 137468
  • Cn (할당되지 않음) : 836601

편집 댓글에서 제안을 추가합니다.


답변

내가 아는 한 가장 비단뱀적이고 효율적인 방법은 다음과 같습니다.

import string

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


답변

다음 unicodedata.category()기능을 사용하여 필터를 설정할 수 있습니다.

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

사용 가능한 범주 는 유니 코드 데이터베이스 문자 속성 에서 175 페이지의 표 4-9를 참조하십시오.


답변

Python 3에서

def filter_nonprintable(text):
    import itertools
    # Use characters of control category
    nonprintable = itertools.chain(range(0x00,0x20),range(0x7f,0xa0))
    # Use translate to remove all non-printable characters
    return text.translate({character:None for character in nonprintable})

.translate ()가 정규식 및 .replace ()와 어떻게 비교되는지에 대해서는 구두점 제거에 대한 이 StackOverflow 게시물을 참조하십시오.

범위는 @Ants Aasma에 표시된대로 유니 코드 문자 데이터베이스 범주nonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc')사용하여 생성 할 수 있습니다 .


답변

다음은 유니 코드 입력으로 작동하며 다소 빠릅니다.

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

내 자신의 테스트에 따르면이 접근 방식은 문자열을 반복하고을 사용하여 결과를 반환하는 함수보다 빠릅니다 str.join.


답변

이 함수는 목록 이해력과 str.join을 사용하므로 O (n ^ 2) 대신 선형 시간으로 실행됩니다.

from curses.ascii import isprint

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


답변

파이썬 3의 또 다른 옵션 :

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