超过一个字节后的lua解析

问题描述

如何在超过一个字节后解析二进制文件? 例如:

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 56 30 30BF 0BD 0EF 0BD EF 0BD 03 2A 5C EF BF BD 03 02 45 24 56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 30BF 0BF 0BF 0BF 0BF 0 0BF 0 30BF 30BF 3 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF

我想在 0x56 0x30 0x30 0x31 之后解析这个。我怎样才能做到这一点?在每个新的 0x56 0x30 0x30 0x31 之前,旧的数据包(字符串)应该结束。

像这样:

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F

56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24

56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF

我已经做了一些类似的事情来解析一个字节到一个表中。但我不能把它变成我的新问题。 这就是1Byte 0x7E后解析的代码

function print_table(tab)
print("Table:") 
for key,value in pairs(tab) do
  io.write(string.format("%02X ",value))  
end
print("\n") 
end

local function read_file(path,callback) 
local file = io.open(path,"rb") 
if not file then 
 return nil
end
local t = {} 
repeat
local str = file:read(4 * 1024)   
for c in (str or ''):gmatch('.') do  
    if c:byte() == 0x7E then 
        callback(t) -- function print_table
        t = {}
    else
        table.insert(t,c:byte())  
    end
end
until not str
file:close() 
return t 
end

local result = {}
function add_to_table_of_tables(t)
table.insert(result,t) 
end

local fileContent = read_file("file.dat",print_table)

重要的是 56 30 30 31 是第一个写在字符串中的。 感谢您的帮助!

我也需要它来从文件中读取我的输入。 我正在像这样阅读我的文件

local function read_file(path) --function read_file
  local file = io.open(path,"rb") -- r read mode and b binary mode
  if not file then return nil end
  local content = file:read "*all" -- *all reads the whole file
  file:close()
  return content
end

解决方法

您可以使用 gsub 将目标子字符串替换为输入字符串唯一的单个字符,我将在此示例中使用 \n。之后,您可以使用 gmatch 来选择一系列不是替换字符的字符。

local input = [[56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24 56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF]]

local pattern ="([^\n]+)"
local rowPrefix = "56 30 30 31"

input = input:gsub(rowPrefix,"\n")

for row in input:gmatch(pattern) do
  print(rowPrefix .. row)
end

输出:

56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 
56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24 
56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 
56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF

获取更多信息的资源:

Programming in Lua: 20.1 – Pattern-Matching Functions

Lua 5.3 Reference Manual: string.gmatch

Lua 5.3 Reference Manual: string.gsub

,

修改此代码:

S=[[56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 EF BF BD 00 EF BF BD 1F 56 30 30 31 01 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 24 56 30 30 31 04 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 02 45 13 00 00 00 56 30 30 31 07 00 00 00 EF BF BD EF BF BD 2A 5C EF BF BD 03 01 45 7E 12 02 24 00 4D EF BF]]
H=[[56 30 30 31]]
E="\n"
S=S:gsub(H,E..H)
S:gsub(E.."([^"..E.."]+)",print)