测试python字符串是否可打印

时间:2010-09-03 14:54:23

标签: python string

我有一些从com-port中提取数据的代码,我想确保在打印之前我得到的是一个可打印的字符串(即ASCII,可能是UTF-8)。这样做有功能吗?我看了上半打的地方,没有任何看起来像我想要的东西。 (string has printable但我没有看到任何内容(在the string methods中),以检查一个字符串中的每个字符是否都在另一个字符串中。

注意:控制字符可打印用于我的目的。


编辑:我正在/正在寻找一个单一的功能,而不是一个自己动手的解决方案:

我最终得到的是:

all(ord(c) < 127 and c in string.printable for c in input_str)

10 个答案:

答案 0 :(得分:45)

正如您所说string module has printable所以只是检查字符串中的所有字符是否都在printable中:

>>> hello = 'Hello World!'
>>> bell = chr(7)
>>> import string
>>> all(c in string.printable for c in hello)
True
>>> all(c in string.printable for c in bell)
False

您可以将两个字符串转换为集合 - 因此该集合将包含字符串中的每个字符一次 - 并检查字符串is a subset of创建的集合是否为可打印字符:

>>> printset = set(string.printable)
>>> helloset = set(hello)
>>> bellset = set(bell)
>>> helloset
set(['!', ' ', 'e', 'd', 'H', 'l', 'o', 'r', 'W'])
>>> helloset.issubset(printset)
True
>>> set(bell).issubset(printset)
False

因此,总而言之,您可能希望这样做:

import string
printset = set(string.printable)
isprintable = set(yourstring).issubset(printset)

答案 1 :(得分:5)

try / except似乎是最好的方式:

def isprintable(s, codec='utf8'):
    try: s.decode(codec)
    except UnicodeDecodeError: return False
    else: return True

我不会依赖string.printable,它可能认为“不可打印”的控制字符通常可以“打印”以用于终端控制目的(例如,在“着色”ANSI转义序列中,如果您的终端是ANSI标准)。但是,当然,这取决于你想要检查这个的确切目的! - )

答案 2 :(得分:4)

>>> # Printable
>>> s = 'test'
>>> len(s)+2 == len(repr(s))
True

>>> # Unprintable
>>> s = 'test\x00'
>>> len(s)+2 == len(repr(s))
False

答案 3 :(得分:3)

此Python 3字符串包含各种特殊字符:

s = 'abcd\x65\x66 äüöë\xf1 \u00a0\u00a1\u00a2 漢字 \a\b\r\t\n\v\\ \231\x9a \u2640\u2642\uffff'

如果您尝试在控制台中显示它(或使用repr),则可以很好地从该字符串中转义所有不可打印的字符:

>>> s
'abcdef äüöëñ \xa0¡¢ 漢字 \x07\x08\r\t\n\x0b\\ \x99\x9a ♀♂\uffff'

足够智能识别,例如水平标签(\t)可打印,但垂直标签(\v)不可打印(显示为\x0b而不是\v)。

其他所有不可打印字符也会在\xNN中显示为\uNNNNrepr。因此,我们可以将其作为测试:

def is_printable(s):
    return not any(repr(ch).startswith("'\\x") or repr(ch).startswith("'\\u") for ch in s)

可能会有一些临界字符,例如不间断的空格(\xa0)在此处被视为不可打印。也许它不应该,但那些特殊的可能是硬编码的。

P.S。

您可以这样做,只从字符串中提取可打印的字符:

>>> ''.join(ch for ch in s if is_printable(ch))
'abcdef äüöëñ ¡¢ 漢字 \r\t\n\\  ♀♂'

答案 4 :(得分:3)

在Python 3中,字符串具有isprintable()方法:

>>> 'a, '.isprintable()
True

对于Python 2.7,请参阅Dave Webb的答案。

答案 5 :(得分:1)

# Here is the full routine to display an arbitrary binary string
# Python 2

ctrlchar = "\n\r| "

# ------------------------------------------------------------------------

def isprint(chh):
    if ord(chh) > 127:
        return False
    if ord(chh) < 32:
        return False
    if chh in ctrlchar:
        return False
    if chh in string.printable:
        return True
    return False


# ------------------------------------------------------------------------
# Return a hex dump formatted string

def hexdump(strx, llen = 16):
    lenx = len(strx)
    outx = ""
    for aa in range(lenx/16):
        outx += " "
        for bb in range(16):
            outx += "%02x " % ord(strx[aa * 16 + bb])
        outx += " | "     
        for cc in range(16):
            chh = strx[aa * 16 + cc]
            if isprint(chh):
                outx += "%c" % chh
            else:
                outx += "."
        outx += " | \n"

    # Print remainder on last line
    remn = lenx % 16 ;   divi = lenx / 16
    if remn:
        outx += " "
        for dd in range(remn):
            outx += "%02x " % ord(strx[divi * 16 + dd])
        outx += " " * ((16 - remn) * 3) 
        outx += " | "     
        for cc in range(remn):
            chh = strx[divi * 16 + cc]
            if isprint(chh):
                outx += "%c" % chh
            else:
                outx += "."
        outx += " " * ((16 - remn)) 
        outx += " | \n"


    return(outx)

答案 6 :(得分:0)

category module中的unicodedata函数可能适合您的需求。例如,您可以使用它来检查字符串中是否有任何控制字符,同时仍允许使用非ASCII字符。

>>> import unicodedata

>>> def has_control_chars(s):
...     return any(unicodedata.category(c) == 'Cc' for c in s)

>>> has_control_chars('Hello 世界')
False

>>> has_control_chars('Hello \x1f 世界')
True

答案 7 :(得分:0)

Mine是一种摆脱任何已知字符集的解决方案。可能会有帮助。

non_printable_chars = set("\n\t\r ")     # Space included intensionally
is_printable = lambda string:bool(set(string) - set(non_printable_chars))
...
...
if is_printable(string):
    print("""do something""")

...

答案 8 :(得分:0)

ctrlchar = "\n\r| "

# ------------------------------------------------------------------------
# This will let you control what you deem 'printable'
# Clean enough to display any binary 

def isprint(chh):
    if ord(chh) > 127:
        return False
    if ord(chh) < 32:
        return False
    if chh in ctrlchar:
        return False
    if chh in string.printable:
        return True
    return False

答案 9 :(得分:0)

在ASCII表中,[\ x20- \ x7e]是可打印的字符。
使用正则表达式检查字符串中是否包含除这些字符之外的其他字符。
您可以确定这是否是可打印的字符串。

>>> import re

>>> # Printable
>>> print re.search(r'[^\x20-\x7e]', 'test')
None

>>> # Unprintable
>>> re.search(r'[^\x20-\x7e]', 'test\x00') != None
True

>>> # Optional expression
>>> pattern = r'[^\t-\r\x20-\x7e]'