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

时间:2008-09-18 13:17:07

标签: python string non-printable

我用来运行

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

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

在Python中没有POSIX正则表达式类,我不能写[:print:]让它意味着我想要的东西。我知道在Python中无法检测字符是否可打印。

你会做什么?

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

13 个答案:

答案 0 :(得分:72)

遗憾的是迭代字符串在Python中相当慢。对于这种事情,正则表达式要快一个数量级。你只需要自己构建角色类。 unicodedata 模块对此非常有用,尤其是 unicodedata.category()函数。有关类别的说明,请参阅Unicode Character Database

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)

答案 1 :(得分:62)

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

import string

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

答案 2 :(得分:11)

您可以尝试使用unicodedata.category()功能设置过滤器:

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

有关可用类别

,请参阅Unicode database character properties中的第175页的表4-9

答案 3 :(得分:9)

在Python 3中,

def filter_nonprintable(text):
    import string
    # Get the difference of all ASCII characters from the set of printable characters
    nonprintable = set([chr(i) for i in range(128)]).difference(string.printable)
    # Use translate to remove all non-printable characters
    return text.translate({ord(character):None for character in nonprintable})

请参阅this StackOverflow post on removing punctuation了解.translate()与正则表达式& .replace()

答案 4 :(得分:5)

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

from curses.ascii import isprint

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

答案 5 :(得分:2)

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

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

这是我发现可以使用Unicode字符/字符串

的唯一方法

有更好的选择吗?

答案 6 :(得分:2)

  

在Python中,没有POSIX正则表达式类

使用regex库时有以下情况:https://pypi.org/project/regex/

它维护得很好,并支持Unicode regex,Posix regex等。用法(方法签名)非常,类似于Python的re

从文档中:

  

[[:alpha:]]; [[:^alpha:]]

     支持

POSIX字符类。这些   通常被视为\p{...}的替代形式。

(我没有隶属关系,只是一个用户。)

答案 7 :(得分:2)

根据@Ber的回答,我建议仅删除Unicode character database categories中定义的控制字符:

import unicodedata
def filter_non_printable(s):
    return ''.join(c for c in s if not unicodedata.category(c).startswith('C'))

答案 8 :(得分:1)

以下一项比上述其他项目表现更快。看看

''.join([x if x in string.printable else '' for x in Str])

答案 9 :(得分:0)

删除'空白'

import re
t = """
\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>
"""
pat = re.compile(r'[\t\n]')
print(pat.sub("", t))

答案 10 :(得分:0)

以下内容适用于Unicode输入,并且速度很快...

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遍历字符串并返回结果的函数要快。

答案 11 :(得分:0)

根据Ants Aasmashawnrad的答案改编而成:

nonprintable = set(map(chr, list(range(0,32)) + list(range(127,160))))
ord_dict = {ord(character):None for character in nonprintable}
def filter_nonprintable(text):
    return text.translate(ord_dict)

#use
str = "this is my string"
str = filter_nonprintable(str)
print(str)

在Python 3.7.7上测试

答案 12 :(得分:-1)

在python 3中还有另一个选择:

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