包格式字符串中的自动重复标志

Posted

技术标签:

【中文标题】包格式字符串中的自动重复标志【英文标题】:auto-repeat flag in a pack format string 【发布时间】:2011-10-23 17:10:14 【问题描述】:

php 中,unpack() 有一个“*”标志,意思是“重复这种格式直到输入结束”。例如,这将打印 97、98、99

$str = "abc";
$b = unpack("c*", $str);
print_r($b);

在python中有这样的东西吗?当然可以了

str = "abc"
print struct.unpack("b" * len(str), str)

但我想知道是否有更好的方法。

【问题讨论】:

JBernardo,您应该考虑将其移至答案。 Unpack format characters in Python的可能重复 【参考方案1】:

在 Python 3.4 及更高版本中,您可以使用新函数struct.iter_unpack

struct.iter_unpack(fmt, buffer)

根据格式字符串 fmt 从缓冲缓冲区中迭代解包。该函数返回一个迭代器,它将从缓冲区中读取相同大小的块,直到其所有内容都被消耗完。缓冲区的字节大小必须是格式所需大小的倍数,这由 calcsize() 反映。 每次迭代都会产生一个由格式字符串指定的元组。

假设我们想用重复格式字符串'<2sc'(2 个字符后跟一个字符,重复直到完成)解压数组b'\x01\x02\x03'*3

使用iter_unpack,您可以执行以下操作:

>>> import struct
>>> some_bytes = b'\x01\x02\x03'*3
>>> fmt = '<2sc'
>>> 
>>> tuple(struct.iter_unpack(fmt, some_bytes))
((b'\x01\x02', b'\x03'), (b'\x01\x02', b'\x03'), (b'\x01\x02', b'\x03'))

如果您想取消嵌套此结果,可以使用 itertools.chain.from_iterable 进行。

>>> from itertools import chain
>>> tuple(chain.from_iterable(struct.iter_unpack(fmt, some_bytes)))
(b'\x01\x02', b'\x03', b'\x01\x02', b'\x03', b'\x01\x02', b'\x03')

当然,您可以使用嵌套推导来做同样的事情。

>>> tuple(x for subtuple in struct.iter_unpack(fmt, some_bytes) for x in subtuple)
(b'\x01\x02', b'\x03', b'\x01\x02', b'\x03', b'\x01\x02', b'\x03')

【讨论】:

【参考方案2】:

struct.unpack 中没有内置这样的功能,但可以定义这样的函数:

import struct

def unpack(fmt, astr):
    """
    Return struct.unpack(fmt, astr) with the optional single * in fmt replaced with
    the appropriate number, given the length of astr.
    """
    # http://***.com/a/7867892/190597
    try:
        return struct.unpack(fmt, astr)
    except struct.error:
        flen = struct.calcsize(fmt.replace('*', ''))
        alen = len(astr)
        idx = fmt.find('*')
        before_char = fmt[idx-1]
        n = (alen-flen)/struct.calcsize(before_char)+1
        fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
        return struct.unpack(fmt, astr)

print(unpack('b*','abc'))
# (97, 98, 99)

【讨论】:

以上是关于包格式字符串中的自动重复标志的主要内容,如果未能解决你的问题,请参考以下文章

关于 unpack() 和 printf() 中的 v 标志的 Perl 问题

html5 - 无法将`\n`格式化为渲染字符串中的新行[重复]

从字符串到整数的转换中的Java数字格式异常[重复]

ValueError:格式错误的节点或字符串:Pandas 中的 0 [重复]

使用jquery插件格式化字符串中的所有数字[重复]

将字符串格式的科学记数法转换为火花数据帧中的数字[重复]