2016-07-20 3 views
2

방화벽 구성 파일에 대한 파서를 쓰고 있습니다. PyParsing과 Python을 처음 접해 보았습니다.다른 문자열 길이를 PyParsing

질문은 어떻게 3 개 이상의 인수가 발생하면 구문 분석합니까 (xxxx, xxxx, xxxx)! = (xxxx, xxxx, xxxx, xxxx), 모든 규칙이 올바르게 작동하고 각 행에 더 이상 3 개의 문자열은 아니지만 [방화벽 [F1]]에는 주소 필드 뒤에 "NAT"가 포함되어 있으며 규칙을 변경하는 방법과 상관없이 무시됩니다.

(DEF printTokens (S, LOC, toks) : #의 S = 오리지널 캐릭터, LOC = 위치 toks = 매칭 토큰)를 사용

넷째 인자 ("NAT")를 사용하는 경우 (2 개)의 출력을 참조하세요 우리가 지울 때. 미리 감사드립니다! 규칙이 구현 된 "NAT"를 포함한 모든 것을 구문 분석해야합니다.

from pyparsing import * 

#===================================GRAMMER================================== 
zone = Literal("zone")  
zoneid = Word(alphanums) 
host = Literal("host") 
hostid = Word(alphanums) 
interface = Literal("interface") 
interfaceid = Word(alphanums) 
firewall = Literal("firewall") 
firewallid = Word(alphanums) 
router = Literal("router") 
routerid = Word(alphanums) 

fstop = Literal(".") 
comma = Suppress(",") #Converter for ignoring the results of a parsed expression. 
slash = Literal("/") 
ocbracket = Literal("{") 
ccbracket = Literal("}") 
sobracket = Literal("[") 
scbracket = Literal("]") 
hyphen = Literal("-") 
underline = Literal("_") 
word = Word(alphas) 


#===================================IP-TYPE================================= 

ip=Combine(Word(nums)+    
     fstop+ Word(nums) + 
     fstop+ Word(nums) + 
     fstop + Word(nums)) 

subnet = Combine(slash +Word(nums)) 

address = ip + Optional(subnet) 


#===================================RULES=================================== 

#adword = address + word 

zoneRule = zone + zoneid + address 
hostRule = host + hostid + ocbracket 
interfaceRule = interface + interfaceid + address 
interfaceRule2 = interface + interfaceid + address + word 
firewallRule = firewall + firewallid + ocbracket 
routerRule = router + routerid + ocbracket 

endRule = ccbracket 


rule = zoneRule | hostRule | interfaceRule | interfaceRule2 | firewallRule | routerRule | endRule 
rules = OneOrMore(rule) 

#===================================DATA===================================== 
details = """zone zone1 10.1.0.0/24     
     zone backbone 10.254.0.0/24 
     zone zone 10.2.0.0/24 
     host ha { 
      interface iha 10.1.0.1 
     } 
     host hb { 
      interface ihb 10.2.0.1 
     } 
     firewall f1 { 
      interface ifla 10.1.0.254 
      interface iflback 10.254.0.101 nat 
     } 
     router r2 { 
      interface ir2back 10.254.0.102 
     } 
     router r3 { 
      interface ir3b 10.2.0.103 
     }""" 

#==================================METHODS================================== 

    def printTokens(s,loc,toks): #s=orig string, loc=location, toks=matched tokens 
    print (toks) 

zoneRule.setParseAction(printTokens) 
hostRule.setParseAction(printTokens) 
interfaceRule.setParseAction(printTokens) 
interfaceRule2.setParseAction(printTokens) #takes in 4 instances where as 3 declared 
firewallRule.setParseAction(printTokens) 
routerRule.setParseAction(printTokens) 
endRule.setParseAction(printTokens) 

rules.parseString(details) 


#================================OUTPUT RESULT WITH NAT================================= 
""" 
['zone', 'zone1', '10.1.0.0', '/24'] 
['zone', 'backbone', '10.254.0.0', '/24'] 
['zone', 'zone', '10.2.0.0', '/24'] 
['host', 'ha', '{'] 
['interface', 'iha', '10.1.0.1']   
['}'] 
['host', 'hb', '{'] 
['interface', 'ihb', '10.2.0.1'] 
['}'] 
['firewall', 'f1', '{'] 
['interface', 'ifla', '10.1.0.254'] 
['interface', 'iflback', '10.254.0.101']""" 
#================================OUTPUT RESULT WITHOUT NAT================================= 
"""['zone', 'zone1', '10.1.0.0', '/24'] 
['zone', 'backbone', '10.254.0.0', '/24'] 
['zone', 'zone', '10.2.0.0', '/24'] 
['host', 'ha', '{'] 
['interface', 'iha', '10.1.0.1'] 
['}'] 
['host', 'hb', '{'] 
['interface', 'ihb', '10.2.0.1'] 
['}'] 
['firewall', 'f1', '{'] 
['interface', 'ifla', '10.1.0.254'] 
['interface', 'iflback', '10.254.0.101'] 
['}'] 
['router', 'r2', '{'] 
['interface', 'ir2back', '10.254.0.102'] 
['}'] 
['router', 'r3', '{'] 
['interface', 'ir3b', '10.2.0.103'] 
['}']""" 
+0

'규칙 = zoneRule | hostRule | interfaceRule | interfaceRule2 | firewallRule | routerRule | endRule'을'rule = zoneRule | hostRule | interfaceRule2 | interfaceRule | firewallRule | routerRule | endRule'. 또한 가능한 경우'interfaceRule2 = interface + interfaceid + address + CaselessLiteral ('nat')'또는'interfaceRule2 = interface + interfaceid + address + oneOf ("nat ext ipv6 other1 other2")와 같이' '. 또한 IPv4 및 IPv6 주소에 대한'pyparsing_common' 정의를 포함하여 2.1.5 릴리스를 살펴보십시오. – PaulMcG

답변

2

임의의 수의 표현식을 특정 구분 기호와 일치 시키려면 PyParsing's delimitedList을 사용하십시오. 기본적으로 구분 기호 주위의 공백을 허용합니다. 공백이 필요없는 combine=True을 추가하십시오.

그러나 문법에 선택적 항목을 허용하려면 선택 항목 만 추가하면됩니다. 사용자 인터페이스 규칙의 경우 대체 할 수

interfaceRule = interface + interfaceid + address 
interfaceRule2 = interface + interfaceid + address + word 

으로 :

interfaceRule = interface + interfaceid + address + Optional(word) 

마지막으로, 게시 된 코드의 실제 문제는 당신이 짧은 손이다는 | 연산자를 사용하는 것입니다 MatchFirst에 대한 양식. MatchFirst는 주어진 옵션 의 순서로 시도하고 의 결과를 먼저과 일치하는 결과를 반환합니다. 짧은 양식이 인 대신 짧은 양식이 ^ 연산자 인 경우, 대신 의 모든 옵션을 시도하고 길이가 가장 긴 문자를 일치로 반환합니다.

+0

'선택 사항'은이 문제에 대한 좋은 제안이지만, 다음 방화벽 규칙의 주요'인터페이스 '를 포함 할 수있는 alphas의 단어 그룹과 일치하므로'word'보다는 더 구체적 일 필요가 있습니다. – PaulMcG

+0

솔루션의 번호를 보내 주셔서 대단히 감사합니다. 규칙을 다시 주문 해 주셔서 감사합니다. 실제로 위의 설명에 따라 선택적 (단어)을 사용하여 ClasslessLiteral ('nat')을 사용하는 단어가 "인터페이스"로 바뀝니다. 한 가지 해결 방법. 유일한 문제는 내가 'nat'병 이상으로 수동으로 그 리터럴을 추가해야만하는 경우입니다. 그러나 질문에 대한 답이 나온다. 고맙습니다. 너의 도움을 간청했다! – vVv

관련 문제