在python中从字符串中剥离不可打印的字符
我过去经常跑步在python中从字符串中剥离不可打印的字符,python,string,non-printable,Python,String,Non Printable,我过去经常跑步 $s =~ s/[^[:print:]]//g; 在Perl上删除不可打印的字符 Python中没有POSIX正则表达式类,我无法编写[:print:]让它代表我想要的内容。我知道Python中没有办法检测字符是否可打印 你会怎么做 编辑:它还必须支持Unicode字符。string.printable方法将很高兴地将它们从输出中删除。 curses.ascii.isprint对于任何unicode字符都将返回false。我现在想到的最好的方法是(感谢上面的python ize
$s =~ s/[^[:print:]]//g;
在Perl上删除不可打印的字符
Python中没有POSIX正则表达式类,我无法编写[:print:]让它代表我想要的内容。我知道Python中没有办法检测字符是否可打印
你会怎么做
编辑:它还必须支持Unicode字符。string.printable方法将很高兴地将它们从输出中删除。
curses.ascii.isprint对于任何unicode字符都将返回false。我现在想到的最好的方法是(感谢上面的python izers) 这是我发现的唯一适用于Unicode字符/字符串的方法
有更好的选择吗?据我所知,最具吸引力/效率的方法是:
import string
filtered_string = filter(lambda x: x in string.printable, myStr)
此函数使用列表理解和str.join,因此它以线性时间而不是O(n^2)运行:
不幸的是,在Python中对字符串进行迭代相当慢。对于这类事情,正则表达式要快一个数量级以上。你只需要自己构建角色类。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)
用于蟒蛇2
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)
对于某些用例,可能更希望使用其他类别(例如,所有来自控制组的类别),尽管这可能会减慢处理时间并显著增加内存使用。每个类别的字符数:
(对照组):65Cc
(格式):161Cf
(代理):2048Cs
(私人使用):137468Co
(未分配):836601Cn
编辑从评论中添加建议。您可以尝试使用
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)
有关Python 3中可用的类别,请参见中第175页的表4-9
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()与regex和.replace()的比较,请参见
如果unicodedata.category(c)='Cc')使用@Ants Aasma.所示的删除“空白”,则可以通过以下方式生成范围:
不可打印=(ord(c)表示范围中的c(chr(i)表示范围中的i(sys.maxunicode))
import re
t = """
\n\t<p> </p>\n\t<p> </p>\n\t<p> </p>\n\t<p> </p>\n\t<p>
"""
pat = re.compile(r'[\t\n]')
print(pat.sub("", t))
重新导入
t=”“”
\n\t\n\t\n\t\n\t\n\t
"""
pat=re.compile(r'[\t\n]')
印刷品(附页(“,t))
下面的一个执行速度比上面其他的快。看一看
''.join([x if x in string.printable else '' for x in Str])
Python中没有POSIX正则表达式类
在使用regex
库时,存在以下问题:
它维护得很好,支持Unicode正则表达式、Posix正则表达式和更多。用法(方法签名)非常类似于Python的re
从文件中:
[[:alpha:][];[[:^alpha:][]
支持POSIX字符类
通常被视为\p{…}
的替代形式
(我不是附属机构,只是一个用户。)python 3中的另一个选项:
re.sub(f'[^{re.escape(string.printable)}]', '', my_string)
以下内容适用于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
返回结果的函数更快,这些函数根据和的答案改编:
根据@Ber的回答,我建议只删除以下定义的控制字符:
导入Unicode数据
def过滤器不可打印:
返回“”。join(如果不是Unicode数据,则c代表s中的c.category(c).startswith('c'))
您可能需要筛选的\u string=''.join(筛选(lambda x:x in string.printable,myStr)这样您就可以得到一个字符串。遗憾的是,string.printable不包含unicode字符,因此输出中不会出现ü或ó…可能还有其他内容?您应该使用列表理解或生成器表达式,而不是filter+lambda。其中一个将在99.9%的时间内更快。“”加入(如果s在string.printable中,则s代表myStr中的s)@AaronGallagher:99.9%的速度?你是从哪里得到这个数字的?性能比较远没有那么差。嗨,William。这种方法似乎删除了所有非ASCII字符。Unicode中有许多可打印的非ASCII字符!这里的“Cc”够了吗?我不知道,我只是在问——在我看来,其他一些“C”分类es也可能是此筛选器的候选项。此函数在发布时删除了一半希伯来文字符。对于给定的两种方法,我都得到了相同的效果。从性能角度来看,string.translate()在这种情况下不是工作得更快吗?请参阅Useall_chars=(unichr(I)表示xrange(sys.maxunicode)中的I)
以避免狭隘的构建错误。对于我来说,control\u chars=='\x00-\x1f\x7f-\x9f'
(在Python 3.5.2上测试)除非您使用的是Python 2.3,否则内部[]是冗余的。“return.”join(c代表c…)并不是很冗余。它们有不同的含义(和性能特征),尽管最终结果是一样的。范围的另一端是否也应该受到保护?:“ord(c)但也有Unicode字符无法打印。您开始的列表理解并没有在最后一行结束。我建议您完全删除开头的括号。谢谢您指出这一点。我据此编辑了文章。这似乎是最直接、最直接的方法。谢谢。@csaboth这三种方法都是有效的,并产生了t同一个集合。您的可能是指定集合文字的最好方法。@AnubhavJhalani您可以向筛选器添加更多Unicode类别。若要在字母之外保留空格和数字,请使用printable={Lu',Ll',Zs',Nd'}
”。加入([c如果0x21这对我和它的1行非常有效。谢谢出于某种原因,这在windows上非常有效,但在linux上无法使用,我不得不将f改为r,但我不确定这是解决方案。听起来你的linux Python太旧了,不支持f字符串。r字符串完全不同,
re.sub(f'[^{re.escape(string.printable)}]', '', my_string)
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('') == ''
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)