Я пытаюсь разобрать текстовый файл и преобразовать его в таблицу (или JSON) с помощью lua. Пример тестового файла выглядит следующим образом:
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 system / openwrt router, вы можете получить аналогичный тестовый файл, используя команду conntrack
или прочитав /proc/net/nf_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
. Я знаю, что за это отвечает код
line = line: match ("^ (.- ([^ =] + =) .-)% 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, но все еще не понимаю, как записывать вывод с помощью %<some_number>
. Почему не работают %1
или %3
?
Я нашел два соответствующих вопроса о стеке: Q1 , Q2. Было бы желательно более глубокое объяснение.
Кроме того, в настоящее время я не могу восстановить значение тайм-аута (5-е слово в строке 1 3598
) или состояние соединения (ESTABLISHED
, [ASSURED]
) с помощью кода, который я здесь предоставил. Я все еще новичок в lua и надеюсь скоро это исправить.
* ПРИМЕЧАНИЕ. Это моя фиксированная версия синтаксического анализатора, доступного в модуле luci sys на маршрутизаторах openwrt. См. исходный код luci.sys для подробностей.
Во время работы над настройкой отношения 12.09 я заметил, что их net.conntrack () не работает из-за сбоя в синтаксическом анализе объекта в надлежащий формат JSON. Соответствующая функция, использующая этот шаблон, указана в файле sys.lua и называется функцией conntrack (обратный вызов) и внутренней функцией _parse_mixed_record (cnt, разделитель). Мой роутер использовал luci-0.11 и lua 5.1.4.