Json 在带括号的Lua中使用模式匹配时,如何使用";%2“;获取捕获组

Json 在带括号的Lua中使用模式匹配时,如何使用";%2“;获取捕获组,json,lua,openwrt,lua-patterns,Json,Lua,Openwrt,Lua Patterns,我试图解析一个文本文件,并使用lua将其转换为一个表(或JSON)。示例测试文件如下所示: ipv4 2 tcp 6 3598 ESTABLISHED src=192.168.1.117 dst=137.194.2.78 sport=59078 dport=80 packets=4 bytes=298 src=137.194.2.78 dst=132.227.127.212 sport=80 dport=59078 packets=3 bytes=567 [ASSURED] m

我试图解析一个文本文件,并使用lua将其转换为一个表(或JSON)。示例测试文件如下所示:

ipv4     2 tcp      6 3598 ESTABLISHED src=192.168.1.117 dst=137.194.2.78 sport=59078 dport=80 packets=4 bytes=298 src=137.194.2.78 dst=132.227.127.212 sport=80 dport=59078 packets=3 bytes=567 [ASSURED] mark=0 use=2
ipv4     2 udp      17 55 src=192.168.1.117 dst=157.56.149.60 sport=49991 dport=3544 packets=5 bytes=445 [UNREPLIED] src=157.56.149.60 dst=132.227.127.212 sport=3544 dport=49991 packets=0 bytes=0 mark=0 use=2
ipv4     2 tcp      6 3420 ESTABLISHED src=192.168.1.104 dst=193.51.224.187 sport=35918 dport=443 packets=19 bytes=2521 src=193.51.224.187 dst=132.227.127.212 sport=443 dport=35918 packets=16 bytes=9895 [ASSURED] mark=0 use=2
ipv4     2 udp      17 59 src=192.168.1.117 dst=192.168.1.255 sport=17500 dport=17500 packets=139 bytes=23908 [UNREPLIED] src=192.168.1.255 dst=192.168.1.117 sport=17500 dport=17500 packets=0 bytes=0 mark=0 use=2
...
请注意,每行中的数据可以根据方向(正向和反向路径流)分成两部分。 如果您有linux系统/openwrt路由器,您可以使用
conntrack
命令或通过读取
/proc/net/nf\u conntrack
获得类似的测试文件

我希望检索以下信息:

{ 1:
    {
    "bytes":    298,
    "src":      "192.168.1.117",
    "sport":    59078,
    "layer4":   "tcp",
    "dst":      "137.194.2.78",
    "dport":    80,
    "layer3":   "ipv4",
    "packets":  4,
    "rbytes":   567,
    "rpackets": 3
    },
{ 2: ...
其中,rbytes、rpackets表示反向的字节和数据包(在我的示例文本文件中,第1行的后半部分)

我的解析器如下所示:*

function conntrack(callback)
local connt = {}
if io.open("conntrack.temp", "r") then

    for line in io.lines("conntrack.temp") do
            line = line:match("^(.-( [^ =]+=).-)%2")
        local entry, flags = _parse_mixed_record(line, " +")

            if flags[6] ~= "TIME_WAIT" then
                entry.layer3 = flags[1]
                entry.layer4 = flags[3]
                for i=1, #entry do
                    entry[i] = nil
                end
                if callback then
                    callback(entry)
                else
                    connt[#connt+1] = entry
                end
            end
    end   
else
    return nil
end
return connt
end

function _parse_mixed_record(cnt, delimiter)
delimiter = delimiter or "  "
local data = {}
local flags = {}

for i, l in pairs(cnt:split("\n")) do
    for j, f in pairs(l:split(delimiter)) do
        local k, x, v = f:match('([^%s][^:=]*) *([:=]*) *"*([^\n"]*)"*')
        if k then
            if x == "" then
                table.insert(flags, k)
            else
                data[k] = v
            end
        end
    end
end

return data, flags
end
调用上述函数(在代码中包含一个简单的
split
方法后),我可以解析文件,直到每行的前半部分。因此,基本上没有解析任何
rbytes
rpackets
。我知道负责这件事的代码是

行=行:匹配(“^(.-([^=]+=).-)%2”)

代码中这一行后面的
print(line)
语句向我显示:

ipv4 2 tcp 6 3598已建立src=192.168.1.117 dst=137.194.2.78 sport=59078 dport=80数据包=4字节=298

因此,该语句使用一种令人困惑的模式匹配来分割文件的每一行,在对它进行了一点研究之后,我有点理解这种模式匹配。我仍然没有得到的部分是捕获模式后出现的
%2
。我知道它用于以某种方式访问捕获的模式,但是我应该如何更改此语句,以便
line
同时包含正向路径字节和数据包计数,以及反向路径? 我的主要问题是:这个语句中的模式到底是什么?我可能会删除这一行来解析整个语句,但我想了解原始编码人员为什么要这样做

我已经阅读了lua模式匹配手册,但仍然对使用
%
捕获输出感到困惑。为什么
%1
%3
不起作用

我发现了两个相关的问题:。请作更深入的解释

此外,目前我无法使用我在此处提供的代码恢复超时值(第1行中的第5个字)或连接状态(
已建立
[ASSURED]
)。我仍然是lua的初学者,希望能很快解决这个问题

*注意:这个解析器是openwrt路由器上luci sys模块中可用的解析器的固定版本。有关详细信息,请参阅


在使用态度调整12.09时,我注意到他们的net.conntrack()无法工作,因为未能将对象解析为正确的JSON格式。sys.lua文件中给出了使用此模式的相关函数,称为函数conntrack(回调)和内部函数_parse_mixed_record(cnt,delimiter)。我的路由器使用了luci-0.11和Lua5.1.4。

这种模式设计为只保留每条线路的前向部分。下面是它是如何做到这一点的。第二个括号,
([^=]+=)
,捕获了表单
“stuff=“
的第一个子字符串。然后,模式末尾的
%2
将仅在相同的字符串
“stuff=“
再次出现时匹配。所以在一条像

ipv4     2 tcp      6 3598 ESTABLISHED src=192.168.1.117 dst=137.194.2.78 sport=59078 dport=80 packets=4 bytes=298 src=137.194.2.78 dst=132.227.127.212 sport=80 dport=59078 packets=3 bytes=567 [ASSURED] mark=0 use=2
第二次捕获将是
“src=“
”,因此第一次捕获(分配给
)将是该行的整个初始部分,直到第二次
src=
出现之前,即该初始部分:

ipv4     2 tcp      6 3598 ESTABLISHED src=192.168.1.117 dst=137.194.2.78 sport=59078 dport=80 packets=4 bytes=298
如果您也想得到后半部分,并将其分配给另一个变量,那么可以将
line=…
语句替换为

line1, _, line2 = line:match("^(.-( [^ =]+=).-)(%2.*)$")
这会将行的前半部分分配给第1行(正如先前分配给第2行的那样),其余部分分配给第2行,从第二次出现
“src=“
”开始。对于上面的示例行,您将得到

line1 = "ipv4     2 tcp      6 3598 ESTABLISHED src=192.168.1.117 dst=137.194.2.78 sport=59078 dport=80 packets=4 bytes=298"
line2 = " src=137.194.2.78 dst=132.227.127.212 sport=80 dport=59078 packets=3 bytes=567 [ASSURED] mark=0 use=2"
注意:介于
第1行
第2行
之间的
用于捕获第二个捕获(这里是字符串
“src=“
),请记住,match会按顺序返回所有捕获,无论您是否需要它们