2013-07-25 4 views
0

텍스트 파일을 구문 분석하고이를 lua를 사용하여 테이블 (JSON)로 변환하려고합니다. 예제 테스트 파일은 다음과 같습니다.Lua에서 괄호로 패턴 일치를 사용할 때 "% 2"를 사용하여 캡처 그룹을 얻는 방법

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 
... 

각 행의 데이터는 방향 (정방향 및 역방향 경로 흐름)에 따라 두 부분으로 나눌 수 있습니다. 리눅스 시스템/오픈 라우터 라우터가있는 경우 conntrack 명령을 사용하거나 /proc/net/nf_conntrack을 사용하여 비슷한 테스트 파일을 얻을 수 있습니다. 내가 검색하고자하는 어떤

에는 다음과 같은 정보가 있습니다 :

rbytes는, rpackets이 (내 예를 들어 텍스트 파일에 라인 (1) 하반기) 반대 방향으로 바이트 패킷에 있습니다
{ 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: ... 

. 다음

내 파서이다 : * 상기 함수를 호출

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 방법을 포함 후), I는 각 라인 전반 개까지 파일 을 파싱 할 수있다. 따라서 기본적으로 rbytes 또는 rpackets은 구문 분석되지 않습니다. ("^ (.- ([^ =] + =) .-) % 2")

print(line)

가 다음 경기 :이 책임이있는 코드가

라인 = 줄 알고 코드 라인이 저 보여준다

IPv4의 TCP (2)을 6 3598 설립 SRC = 192.168.1.117 DST = 137.194.2.78 스포츠 = 59,078 패킷 dport = 80 = 4 바이트 = 그래서, 298

상태 nt는 약간 혼자서 놀고 이해하는 혼란스러운 패턴 매칭을 사용하여 파일의 각 라인을 나눕니다. 내가 아직 얻지 못하는 부분은 패턴을 캡처 한 후에 발생하는 %2입니다. 나는 그것이 잡힌 패턴에 어떻게 든 접근하는 데 사용된다는 것을 알고 있지만 line에 역방향 경로뿐만 아니라 순방향 경로 바이트와 패킷 수를 모두 포함하도록이 구문을 어떻게 변경해야합니까? 내 질문은 : 정확히이 성명의 패턴은 무엇입니까? 전체 문장을 파싱하려면이 행을 제거해야하지만 원래 코더가이 작업을 수행하는 이유를 알고 싶었습니다.

나는 lua 패턴 매칭 매뉴얼을 밟아 왔지만, 여전히 출력을 캡처하는 것은 %<some_number>과 혼동 스럽다. %1 또는 %3이 작동하지 않는 이유는 무엇입니까?

두 개의 관련 스택 오버 플로우 질문 : Q1, Q2. 더 깊은 설명은 인정 될 것이다.

또한 현재 여기서 제공 한 코드를 사용하여 시간 초과 값 (line1의 5 번째 단어 3598) 또는 연결 상태 (ESTABLISHED, [ASSURED])를 복구 할 수 없습니다. 나는 아직 루아에서 초보자이며 조만간 이것을 갈길 원합니다.

* 참고 :이 파서는 openwrt 라우터의 luci sys 모듈에서 사용할 수있는 고정 버전입니다.자세한 내용은 original luci.sys sourcecode을 참조하십시오.

태도 조정 12.09에서 작업하면서 올바른 JSON 형식으로 개체를 구문 분석하지 못해서 net.conntrack()이 작동하지 않는 것으로 나타났습니다. 이 패턴을 사용하는 관련 함수는 function conntrack (콜백) 및 internal function _parse_mixed_record (cnt, delimiter)라고하는 sys.lua 파일에 제공됩니다. 내 라우터는 luci-0.11과 lua 5.1.4를 사용했습니다.

답변

0

이 패턴은 각 라인의 앞쪽 부분만을 유지하도록 설계되었습니다. 방법은 다음과 같습니다. 두 번째 괄호 ([^ =]+=)" stuff=" 형식의 첫 번째 부분 문자열을 캡처합니다. 패턴의 끝에있는 %2은 동일한 문자열 인 " stuff="이 다시 나타나는 경우에만 일치합니다. 때까지 line에 할당 된 것을 첫 번째 캡처, 라인의 전 초기 부분 수 있도록 그래서

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 

, 당신은

,691,363으로 line = ... 문을 대체 할 수있는 : 초기 부분이 나타납니다210
line1, _, line2 = line:match("^(.-([^ =]+=).-)(%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" 

주를 얻을 것 : line1line2 사이의 _은 (문자열 " src=" 여기있는)에 일치하는 모든 캡처를 반환 기억 두 번째 캡처를 잡으려고있다 당신이 원하든 원치 않든간에