【问题标题】:Python unpack string in to arrayPython将字符串解包到数组中
【发布时间】:2012-06-18 23:21:38
【问题描述】:

我每天都在使用 Ruby,但我在 Python 中遇到了问题。我发现这些语言非常相似......但是我从 Ruby 迁移时遇到了一些问题:)

请帮我在 python 中转换这个动作:

   string = "qwerty2012"
   (var, some_var, another_var)  = string.unpack("a1a4a*")

这应该从字符串返回三个具有解压值的变量:

   var         = "q"      # a1
   some_var    = "wert"   # a4
   another_var = "y2012"  # a*

帮我用 Python 表示它 谢谢!

【问题讨论】:

  • 你可能不想命名变量string
  • 其实string 没问题。 Python 中的类型是str
  • @ChinmayKanchi,是的,但是还有字符串模块,我们不知道 OP 是否正在导入它,因此将 string 分配给新的东西会将其从命名空间中删除。一种不好的做法。
  • @Chinmay 但是string 包仍然存在 - 但它可能不是特别成问题。
  • 出于某种原因,我认为该模块被称为strings。猜猜这说明了我发现自己使用它的频率。是的,将某些东西命名为标准模块并不是一个好主意。

标签: python arrays string


【解决方案1】:
s = "qwerty2012"
(a, b, c) = s[:1], s[1:5], s[5:]

【讨论】:

  • Levon,对不起。你是第一个!谢谢!
【解决方案2】:

Python 确实有一个名为struct 的类似模块。它缺乏以与Ruby and PHP lifted from Perl 相同的方式抓取字符串的其余部分 的能力。不过,您几乎可以到达那里:

>>> import struct
>>> s = 'qwerty2012'
>>> struct.unpack_from('1s4s', s)
('q', 'wert')
>>> def my_unpack(format, packed_string):
...    result = []
...    result.extend(struct.unpack_from(format, packed_string))
...    chars_gobbled = struct.calcsize(format)
...    rest = packed_string[chars_gobbled:]
...    if rest:
...        result.append(rest)
...    return result
...
>>> my_unpack('1s4s', 'qwerty2012')
['q', 'wert', 'y2012']
>>> my_unpack('1s4s', 'qwert')
['q', 'wert']
>>> [hex(x) for x in my_unpack('<I', '\xDE\xAD\xBE\xEF')]
['0xefbeadde']

我希望 struct 模块实现了 Perl 的 unpackpack 的其余部分,因为它们对于撕开二进制数据包非常有用,但是唉。

【讨论】:

    【解决方案3】:
    s = "qwerty2012"
    var, some_var, another_var = s[:1], s[1:5], s[5:]
    

    将分别做赋值和屈服:

    q
    wert
    y2012
    

    上面的赋值使用了Python Docs 中描述的slice notation。这篇 SO 帖子 Good Primer for Python Slice Notation 也给出了很好的解释。

    【讨论】:

      【解决方案4】:

      这是unpack的初步再现:

      import re
      import StringIO
      
      def unpack(s, fmt):
          fs = StringIO.StringIO(s)
          res = []
          for do,num in unpack.pattern.findall(fmt):
              if num == '*':
                  num = len(s)
              elif num == '':
                  num = 1
              else:
                  num = int(num)
              this = unpack.types[do](num, fs)
              if this is not None:
                  res.append(this)
          return res
      
      unpack.types = {
          '@': lambda n,s: s.seek(n),             # skip to offset
          'a': lambda n,s: s.read(n),             # string
          'A': lambda n,s: s.read(n).rstrip(),    # string, right-trimmed
          'b': lambda n,s: bin(reduce(lambda x,y:256*x+ord(y), s.read(n), 0))[2:].zfill(8*n)[::-1],   # binary, LSB first
          'B': lambda n,s: bin(reduce(lambda x,y:256*x+ord(y), s.read(n), 0))[2:].zfill(8*n)          # binary, MSB first
      }
      unpack.pattern = re.compile(r'([a-zA-Z@](?:_|!|<|>|!<|!>|0|))(\d+|\*|)')
      

      它适用于您给定的示例,

      unpack("qwerty2012", "a1a4a*")  # -> ['q', 'wert', 'y2012']
      

      但有一长串尚未实现的数据类型(请参阅the documentation)。

      【讨论】:

        【解决方案5】:

        这可能会简化您从 Ruby 的迁移:

        import re
        import struct
        
        def unpack(format, a_string):
            pattern = r'''a(\*|\d+)\s*'''
            widths = [int(w) if w is not '*' else 0 for w in re.findall(pattern, format)]
            if not widths[-1]: widths[-1] = len(a_string) - sum(widths)
            fmt = ''.join('%ds' % f for f in widths)
            return struct.unpack_from(fmt, a_string)
        
        (var, some_var, another_var) = unpack('a1a4a*', 'qwerty2012')  # also 'a1 a4 a*' OK
        print (var, some_var, another_var)
        

        输出:

        ('q', 'wert', 'y2012')
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-04
          • 1970-01-01
          • 1970-01-01
          • 2012-07-07
          • 1970-01-01
          • 2021-09-17
          相关资源
          最近更新 更多