我曾经经常跑步。
$s =~ s/[^[:print:]]//g;
使用Perl来清除非可打印字符。
在Python中没有POSIX正则表达式类,我不能编写[:print:]表示我想要的意思。在Python中,我不知道有什么方法可以检测字符是否可打印。
你会怎么做?
编辑:它必须支持Unicode字符。string.printable方式将愉快地从输出中剥离它们。curses.ascii.isprint对于任何Unicode字符都将返回false。
我曾经经常跑步。
$s =~ s/[^[:print:]]//g;
使用Perl来清除非可打印字符。
在Python中没有POSIX正则表达式类,我不能编写[:print:]表示我想要的意思。在Python中,我不知道有什么方法可以检测字符是否可打印。
你会怎么做?
编辑:它必须支持Unicode字符。string.printable方式将愉快地从输出中剥离它们。curses.ascii.isprint对于任何Unicode字符都将返回false。
在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
(控制):65Cf
(格式):161Cs
(代理):2048Co
(专用区):137468Cn
(未分配):836601编辑 添加了评论中的建议。
all_chars = (unichr(i) for i in xrange(sys.maxunicode))
来避免出现窄版构建错误。 - danmichaelocontrol_chars == '\x00-\x1f\x7f-\x9f'
。这意味着控制字符的范围是在十六进制表示下的00到1F,以及7F到9F之间。 - AXOimport 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)
请查看Unicode数据库字符属性第175页的表格4-9,了解可用的类别。
printable = set(['Lu', 'Ll'])
,对吧? - Fabrizio Mianoprintable = {'Lu','Ll','Zs','Nd'}
。 - Ber以下代码适用于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
返回结果的函数更快。
LINE_BREAK_CHARACTERS = set(["\n", "\r"])
以及 and not chr(i) in LINE_BREAK_CHARACTERS
。 - pir在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})
请看这个StackOverflow的帖子关于如何使用.translate()与正则表达式和.replace()相比移除标点符号
范围可以通过nonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc')
来生成,如@Ants Aasma所示,使用Unicode字符数据库类别
text.translate({c:None for c in itertools.chain(range(0x00,0x20),range(0x7f,0xa0))})
。 - darkdragonfrom curses.ascii import isprint
def printable(input):
return ''.join(char for char in input if isprint(char))
Python 3 中的另一种选项:
re.sub(f'[^{re.escape(string.printable)}]', '', my_string)
r'[^' + re.escape(string.printable) + r']'
。 (我认为在这里使用re.escape()
并不完全正确,但如果它能工作...) - tripleeeimport unicodedata
def filter_non_printable(s):
return ''.join(c for c in s if not unicodedata.category(c).startswith('C'))
startswith('C')
有所发现,但在我的测试中,这比任何其他解决方案都要慢得多。 - Big McLargeHugeif unicodedata.category(c)[0] != 'C'
代替。它的性能更好吗?如果你更注重执行速度而不是内存需求,可以像https://dev59.com/1XVD5IYBdhLWcg3wGHeu#93029中所示预先计算表格。 - darkdragon用一种优雅的pythonic方法从字符串中去除“不可打印”字符的解决方案是,结合isprintable()字符串方法和生成器表达式或列表推导式(取决于字符串的大小)。
''.join(c for c in my_string if c.isprintable())
str.isprintable() 如果字符串中的所有字符都是可打印的或者字符串为空,则返回True,否则返回False。不可打印字符是Unicode字符数据库中被定义为“其他”或“分隔符”的那些字符,但ASCII空格(0x20)被视为可打印。 (请注意,在此上下文中,“可打印”字符指在对字符串调用repr()时不应该进行转义的字符。这与写入sys.stdout或sys.stderr的字符串处理无关。)
def filter_non_printable(str):
return ''.join([c for c in str if ord(c) > 31 or ord(c) == 9])
这是我发现的唯一适用于Unicode字符/字符串的方法
还有更好的选择吗?
regex.sub(r'[^[:print:]]+', '', text)
即可。当然,还有很多其他选择。 - Wiktor Stribiżewregex.sub(r'[^[:print:]]+', '', text)
即可。当然,还有很多其他选择。 - undefined