Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何从包含二进制数据的字符串中提取模式_Arrays_Ruby_Ascii_Extraction - Fatal编程技术网

Arrays 如何从包含二进制数据的字符串中提取模式

Arrays 如何从包含二进制数据的字符串中提取模式,arrays,ruby,ascii,extraction,Arrays,Ruby,Ascii,Extraction,我的这个数组来自前面的a=array.unpack(“C*”)命令 a = [9, 32, 50, 53, 56, 53, 57, 9, 73, 78, 70, 79, 9, 73, 78, 70, 79, 53, 9, 32, 55, 52, 32, 50, 51, 32, 48, 51, 32, 57, 50, 32, 48, 48, 32, 48, 48, 32, 48, 48, 32, 69, 67, 32, 48, 50, 32, 49, 48, 32, 48,

我的这个数组来自前面的
a=array.unpack(“C*”)
命令

a = [9, 32, 50, 53, 56, 53, 57, 9, 73, 78, 70, 79, 9, 73, 78, 70, 79, 53, 9, 
     32, 55, 52, 32, 50, 51, 32, 48, 51, 32, 57, 50, 32, 48, 48, 32, 48, 48, 32, 
     48, 48, 32, 69, 67, 32, 48, 50, 32, 49, 48, 32, 48, 48, 32, 69, 50, 32, 48, 
     48, 32, 55, 55, 9, 0, 0, 0, 0, 1, 12, 1, 0, 0, 0, 57, 254, 70, 6, 1, 6, 0, 3, 
     0, 3, 198, 0, 2, 198, 31, 147, 23, 0, 226, 7, 12, 17, 18, 56, 55, 3, 101, 1, 
     1, 0, 134, 7, 145, 5, 148, 37, 150, 133, 241, 135, 5, 22, 109, 145, 53, 38, 
     171, 4, 3, 2, 6, 192, 173, 22, 160, 20, 48, 18, 6, 9, 42, 134, 58, 0, 137, 97, 
     58, 1, 0, 164, 5, 48, 3, 129, 1, 7, 225, 16, 2, 1, 1, 4, 11, 9, 1, 10, 10, 6, 
     2, 19, 105, 145, 103, 116, 226, 35, 48, 3, 194, 1, 242, 48, 3, 194, 1, 241, 48, 
     3, 194, 1, 246, 48, 3, 194, 1, 245, 48, 3, 194, 1, 244, 48, 3, 194, 1, 243, 48, 
     3, 194, 1, 247, 177, 13, 10, 1, 1, 4, 8, 10, 6, 2, 19, 105, 145, 103, 116, 0, 0, 
     42, 3, 0, 0, 48, 48, 48, 48, 48, 48, 48, 50, 9, 82, 101, 99, 101, 105, 118, 101, 
     9, 50, 51, 9, 77, 111, 110, 32, 32]
当我转换为chr时,它如下所示:

 irb(main):4392:0> a.map(&:chr).join
 => "\t 25859\tINFO\tINFO5\t 74 23 03 92 00 00 00 EC 02 10 00 E2 00 77\t\x00\x00\x00\x00
 \x01\f\x01\x00\x00\x009\xFEF\x06\x01\x06\x00\x03\x00\x03\xC6\x00\x02\xC6\x1F\x93\x17\x00
 \xE2\a\f\x11\x1287\x03e\x01\x01\x00\x86\a\x91\x05\x94%\x96\x85\xF1\x87\x05\x16m\x915&\xAB
 \x04\x03\x02\x06\xC0\xAD\x16\xA0\x140\x12\x06\t*\x86:\x00\x89a:\x01\x00\xA4\x050\x03\x81
 \x01\a\xE1\x10\x02\x01\x01\x04\v\t\x01\n\n\x06\x02\x13i\x91gt\xE2#0\x03\xC2\x01\xF20\x03
 \xC2\x01\xF10\x03\xC2\x01\xF60\x03\xC2\x01\xF50\x03\xC2\x01\xF40\x03\xC2\x01\xF30\x03\xC2
 \x01\xF7\xB1\r\n\x01\x01\x04\b\n\x06\x02\x13i\x91gt\x00\x00*\x03\x00\x000000..."
我想提取
INFO5\t
\t..之间的十六进制值,
因此输出为

 "74 23 03 92 00 00 00 EC 02 10 00 E2 00 77"     
我像下面这样做,但只删除了第一个不需要的部分并留下
\n\n\x06…000

我怎样才能解决这个问题

irb(main)>: a.map(&:chr).join.gsub(/(\t .*\t )|(\t.*)/,"")
=> "74 23 03 92 00 00 00 EC 02 10 00 E2 00 77\n\n\x06\x02\x13i\x91gt\xE2#0
\x03\xC2\x01\xF20\x03\xC2\x01\xF10\x03\xC2\x01\xF60\x03\xC2\x01\xF50\x03\xC2
\x01\xF40\x03\xC2\x01\xF30\x03\xC2\x01\xF7\xB1\r\n\x01\x01\x04\b\n\x06\x02\
x13i\x91gt\x00\x00*\x03\x00\x0000000002"
提前谢谢你的帮助

UDPATE

下面附上的示例二进制文件

  • 我假设您不需要非ascii字节,所以在第一步中,我使用
    take\u while
  • 然后我使用
    map(&:chr)将int转换为字符串
  • 最后,我使用一个正则表达式来匹配它们,该正则表达式假定感兴趣的部分位于
    INFO5\t
    和next
    \t
    之间
  • --

  • 我假设您不需要非ascii字节,所以在第一步中,我使用
    take\u while
  • 然后我使用
    map(&:chr)将int转换为字符串
  • 最后,我使用一个正则表达式来匹配它们,该正则表达式假定感兴趣的部分位于
    INFO5\t
    和next
    \t
    之间
  • --


    我想你的意思是
    a=str.unpack(“C*”)
    ——你可以
    解包
    字符串,但不能解包数组

    要获得想要的结果,根本不需要使用
    unpack
    -只需执行正则表达式:

    str.match(/INFO5\t(.*?)\t/).to_a[1]
    # => " 74 23 03 92 00 00 00 EC 02 10 00 E2 00 77"
    
    请注意,结果中有一个前导空格,但您可以根据需要调整正则表达式;我不打算猜测这种格式的规格

    小贴士:

    • 需要
      *?
      中的
      使
      *
      非贪婪
    • to_a
      可避免
      匹配
      未找到任何内容时引发错误

    编辑

    您关于“UTF-8中的无效字节序列”的评论表明,您的数据可能是ASCII-8BIT(即,它与UTF-8不兼容),但它存储在编码属性为“UTF-8”的字符串中。如果您解释如何获得该字符串,这将有助于解释,因为字符串的编码似乎错误

    解决方案1(这非常理想):

    以ASCII-8BIT格式读入文件:

    str = File.read("input.dat", encoding: 'ASCII-8BIT')
    
    解决方案2(如果无法控制输入编码,这是一种解决方法):

    完成此操作后,
    .match
    应该可以工作

    进一步解释

    您的
    映射(&:chr).join
    工作的原因是
    .chr
    将生成
    US-ASCII
    ASCII-8BIT
    字符串(后者发生在127以上的字节),而不会生成
    UTF-8

    当您
    join
    这些字符串时,如果任何字节大于127,则结果为
    ASCII-8BIT
    。因此,这实际上与调用
    force_编码(“ASCII-8BIT”)
    相同,只是
    map
    /
    join
    不像
    force_编码那样修改原始字符串的编码


    1
    unpack
    是不必要的,因为
    a.map(&:chr).join
    arr.pack('C*')
    相同,它提供原始的
    str
    。即使您必须
    unpack
    字符串用于其他目的,我建议使用原始字符串,而不是重新打包数组。也许您可以将其封装到数据结构中,例如:

    i_data = InfoData.new(str)
    i_data.bytes  # array of bytes
    i_data.hex_string  # "74 23 03 ..."
    

    请注意,上面的代码不能按原样工作-您需要自己编写
    InfoData
    类。

    我假定您的意思是
    a=str.unpack(“C*”)
    -您可以
    解压
    字符串,但不能解压数组

    要获得想要的结果,根本不需要使用
    unpack
    -只需执行正则表达式:

    str.match(/INFO5\t(.*?)\t/).to_a[1]
    # => " 74 23 03 92 00 00 00 EC 02 10 00 E2 00 77"
    
    请注意,结果中有一个前导空格,但您可以根据需要调整正则表达式;我不打算猜测这种格式的规格

    小贴士:

    • 需要
      *?
      中的
      使
      *
      非贪婪
    • to_a
      可避免
      匹配
      未找到任何内容时引发错误

    编辑

    您关于“UTF-8中的无效字节序列”的评论表明,您的数据可能是ASCII-8BIT(即,它与UTF-8不兼容),但它存储在编码属性为“UTF-8”的字符串中。如果您解释如何获得该字符串,会有所帮助,因为该字符串的编码似乎是错误的

    解决方案1(这非常理想):

    以ASCII-8BIT格式读入文件:

    str = File.read("input.dat", encoding: 'ASCII-8BIT')
    
    解决方案2(如果无法控制输入编码,这是一种解决方法):

    完成此操作后,
    .match
    应该可以工作

    进一步解释

    您的
    映射(&:chr).join
    工作的原因是
    .chr
    将生成
    US-ASCII
    ASCII-8BIT
    字符串(后者发生在127以上的字节),而不会生成
    UTF-8

    当您
    join
    这些字符串时,如果任何字节大于127,则结果为
    ASCII-8BIT
    。因此,这实际上与调用
    force_编码(“ASCII-8BIT”)
    相同,只是
    map
    /
    join
    不像
    force_编码那样修改原始字符串的编码


    1
    unpack
    是不必要的,因为
    a.map(&:chr).join
    arr.pack('C*')
    相同,它提供原始的
    str
    。即使您必须
    unpack
    字符串用于其他目的,我建议使用原始字符串,而不是重新打包数组。也许你可以把它封装成一个数据包
    a = [9, 32, 50, 53, 56, 53, 57, 9, 73, 78, 70, 79, 9, 73, 78, 70, 79, 53, 9, 
         32, 55, 52, 32, 50, 51, 32, 48, 51, 32, 57, 50, 32, 48, 48, 32, 48, 48,
         32, 48, 48, 32, 69, 67, 32, 48, 50, 32, 49, 48, 32, 48, 48, 32, 69, 50,
         32, 48, 48, 32, 55, 55, 9, 0, 0]
    
    str = a.pack("C*")
      #=> "\t 25859\tINFO\tINFO5\t 74 23 03 92 00 00 00 EC 02 10 00 E2 00 77\t\x00\x00"
    
    str[/(?<=INFO5\t).+?(?=\t)/].strip
      #=> "74 23 03 92 00 00 00 EC 02 10 00 E2 00 77" 
    
    "abc\td\tef"[/(?<=a).+(?=\t)/]
      #=> "bc\td" 
    
    pfix = "INFO5\t".unpack("C*")
      #=> [73, 78, 70, 79, 53, 9]
    pfix_size = pfix.size
      #=> 6 
    sfix = [prefix.last]
      #=> [9]
    sfix_size = sfix.size
    start = idx_start(a, pfix) + pfix_size
      #=> 19
    a[start..idx_start(a[start..-1], sfix) + start - 1].pack("C*").strip
      #=> "74 23 03 92 00 00 00 EC 02 10 00 E2 00 77"
    
    def idx_start(a, arr)
      arr_size = arr.size
      a.each_index.find { |i| a[i, arr_size] == arr }
    end