98

私は走っていた

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

Perl では、印刷できない文字を取り除くことができます。

Python には POSIX 正規表現クラスがなく、 [:print:] を自分の望む意味で書くことはできません。文字が印刷可能かどうかをPythonで検出する方法がわかりません。

あなたならどうしますか?

編集: Unicode 文字もサポートする必要があります。string.printable の方法は、それらを出力から喜んで取り除きます。curses.ascii.isprint は、Unicode 文字に対して false を返します。

4

14 に答える 14

90

残念ながら、文字列の反復処理は Python ではかなり遅くなります。この種の処理では、正規表現の方が桁違いに高速です。文字クラスを自分で構築するだけです。これにはunicodedataモジュール、特にunicodedata.category()関数が非常に役立ちます。カテゴリの説明については、Unicode 文字データベースを参照してください。

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

編集コメントからの提案の追加。

于 2008-09-18T14:28:04.380 に答える
79

私の知る限り、最もpythonic/効率的な方法は次のとおりです。

import string

filtered_string = filter(lambda x: x in string.printable, myStr)
于 2008-09-18T13:23:14.690 に答える
20

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)

使用可能なカテゴリについては、 Unicode データベースの文字プロパティの表 4-9 (175 ページ) を参照してください。

于 2008-09-18T15:25:37.923 に答える
6

この関数はリスト内包表記と str.join を使用するため、O(n^2) ではなく線形時間で実行されます。

from curses.ascii import isprint

def printable(input):
    return ''.join(char for char in input if isprint(char))
于 2008-09-18T13:26:00.143 に答える
2

私が今思いついた最高のものは(上記のpython-izersに感謝します)

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

これは、Unicode文字/文字列で機能することがわかった唯一の方法です

より良いオプションはありますか?

于 2008-09-18T13:17:35.843 に答える