从python中的字符串中剥离不可打印的字符

时间:2020-03-06 14:21:13  来源:igfitidea点击:

我用来跑步

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

在Perl上摆脱不可打印的字符。

在Python中,没有POSIX正则表达式类,因此我无法编写[:print:]来表示我想要的含义。我不知道在Python中无法检测字符是否可打印。

你会怎么做?

编辑:它也必须支持Unicode字符。 string.printable方式会很乐意将它们从输出中剥离。
curses.ascii.isprint将为任何unicode字符返回false。

解决方案

我现在想出的最好的是(由于上面的python-izers)

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

这是我发现可用于Unicode字符/字符串的唯一方法

还有更好的选择吗?

据我所知,最pythonic /最有效的方法是:

import string

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

此函数使用列表推导和str.join,因此它以线性时间而不是O(n ^ 2)的形式运行:

from curses.ascii import isprint

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

不幸的是,在Python中遍历字符串相当慢。对于这种事情,正则表达式的速度要快一个数量级。我们只需要自己构建角色类即可。 unicodedata模块对此非常有帮助,尤其是unicodedata.category()函数。有关类别的说明,请参见Unicode字符数据库。

import unicodedata, re

all_chars = (unichr(i) for i in xrange(0x110000))
control_chars = ''.join(c for c in all_chars if unicodedata.category(c) == 'Cc')
# or equivalently and much more efficiently
control_chars = ''.join(map(unichr, range(0,32) + range(127,160)))

control_char_re = re.compile('[%s]' % re.escape(control_chars))

def remove_control_chars(s):
    return control_char_re.sub('', s)

我们可以尝试使用unicodedata.category()函数设置过滤器:

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

有关可用类别,请参见Unicode数据库字符属性。