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

Vin*_*vic 81 python string non-printable

我用来跑

$s =~ s/[^[:print:]]//g;
Run Code Online (Sandbox Code Playgroud)

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

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

你会怎么做?

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

Ant*_*sma 76

遗憾的是,迭代字符串在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)
Run Code Online (Sandbox Code Playgroud)

  • 'Cc'在这里足够吗?我不知道,我只是问 - 在我看来,其他一些'C'类别也可能是这个过滤器的候选者. (4认同)
  • 对我来说`control_chars =='\ x00-\x1f\x7f-\x9f'`(在Python 3.5.2上测试过) (3认同)
  • 已发布的此函数删除了一半的希伯来字符。对于给定的两种方法,我得到了相同的效果。 (2认同)
  • 从性能角度来看,在这种情况下 string.translate() 不会工作得更快吗?请参阅http://stackoverflow.com/questions/265960/best-way-to-strip-punctuation-from-a-string-in-python (2认同)
  • 使用`all_chars =(unichr(i)for i in xrange(sys.maxunicode))`来避免窄的构建错误. (2认同)

Wil*_*ler 65

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

import string

filtered_string = filter(lambda x: x in string.printable, myStr)
Run Code Online (Sandbox Code Playgroud)

  • 您应该使用列表推导或生成器表达式,而不是filter + lambda.其中一个将99.9%的时间更快.''.join(对于myStr中的s,如果s在string.printable中) (16认同)
  • 可悲的是string.printable不包含unicode字符,因此ü或ó不会出现在输出中...也许还有别的东西? (10认同)
  • 你可能想要filter_string =''.join(filter(lambda x:x in string.printable,myStr),这样你就可以得到一个字符串. (9认同)
  • 嗨威廉.此方法似乎删除所有非ASCII字符.Unicode中有许多可打印的非ASCII字符! (4认同)
  • @AaronGallagher:快了99.9%?你从那里采摘那个数字?性能比较远没那么糟糕. (3认同)
  • @ChrisMorgan:迟到的反应,但声称它几乎总是会更快,而不是它会更快,更快. (2认同)

Ber*_*Ber 14

您可以尝试使用以下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)
Run Code Online (Sandbox Code Playgroud)

请参阅可用类别的Unicode数据库字符属性

  • 这似乎是最直接、最直接的方法。谢谢。 (2认同)
  • @CsabaToth 所有三个都是有效的并且产生相同的集合。您的方法可能是指定集合文字的最好方法。 (2认同)
  • @AnubhavJhalani 您可以向过滤器添加更多 Unicode 类别。要保留字母以外的空格和数字,请使用 `printable = {'Lu', 'Ll', Zs', 'Nd'}` (2认同)

Chr*_*isP 12

以下将与 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('') == ''
Run Code Online (Sandbox Code Playgroud)

我自己的测试表明,这种方法比迭代字符串并使用str.join.


sha*_*rad 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})
Run Code Online (Sandbox Code Playgroud)

有关.translate()与regex&.replace()的比较,请参阅此StackOverflow帖子,删除标点符号


小智 7

python 3中的另一个选项:

re.sub(f'[^{re.escape(string.printable)}]', '', my_string)
Run Code Online (Sandbox Code Playgroud)


dar*_*gon 6

根据 @Ber 的回答,我建议仅删除Unicode 字符数据库类别中定义的控制字符:

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


Kir*_*ser 5

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

from curses.ascii import isprint

def printable(input):
    return ''.join(char for char in input if isprint(char))
Run Code Online (Sandbox Code Playgroud)

  • `滤波器(isprint判断,输入)` (2认同)

Tho*_*yhr 5

从 python 中的字符串中剥离“不可打印”字符的一个优雅的 pythonic 解决方案是根据用例将 isprintable() 字符串方法与生成器表达式或列表理解一起使用。字符串的大小:

\n
    ''.join(c for c in my_string if c.isprintable())\n
Run Code Online (Sandbox Code Playgroud)\n

str.isprintable()\n如果字符串中的所有字符均可打印或字符串为空,则返回 True,否则返回 False。不可打印字符是在 Unicode 字符数据库中定义为 \xe2\x80\x9cOther\xe2\x80\x9d 或 \xe2\x80\x9cSeparator\xe2\x80\x9d 的字符,但被视为可打印的 ASCII 空格 (0x20) 除外。(请注意,此上下文中的可打印字符是在字符串上调用 repr() 时不应转义的字符。它与写入 sys.stdout 或 sys.stderr 的字符串的处理无关。)

\n