Python py解析不同的字符串长度

Python py解析不同的字符串长度,python,parsing,firewall,rules,pyparsing,Python,Parsing,Firewall,Rules,Pyparsing,我正在为防火墙配置文件编写解析器。 一般来说,我不熟悉PyParsing和Python 问题是如果出现3个以上的参数,(xxxx,xxxx,xxxx)!=(xxxx,xxxx,xxxx,xxxx),如果每行包含的字符串不超过3个,则所有规则都可以正常工作并正确解析所有内容,但我们可以看到[Firewall[F1]]在地址字段后包含“NAT”,并且无论我们如何更改规则都会被忽略 使用(def打印标记(s、loc、toks):#s=原始字符串,loc=位置,toks=匹配标记) 当使用第四个参数(“

我正在为防火墙配置文件编写解析器。 一般来说,我不熟悉PyParsing和Python

问题是如果出现3个以上的参数,(xxxx,xxxx,xxxx)!=(xxxx,xxxx,xxxx,xxxx),如果每行包含的字符串不超过3个,则所有规则都可以正常工作并正确解析所有内容,但我们可以看到[Firewall[F1]]在地址字段后包含“NAT”,并且无论我们如何更改规则都会被忽略

使用(def打印标记(s、loc、toks):#s=原始字符串,loc=位置,toks=匹配标记)

当使用第四个参数(“NAT”)和删除它时,请查看两个输出。 提前谢谢!需要解析所有内容,包括实现规则的“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']
['}']"""

如果要使用某个分隔符匹配任意数量的表达式,请使用。默认情况下,它允许在分隔符周围使用空格;添加
combine=True
以不需要空格

但是,如果您想在语法中允许可选项,您应该只添加一个可选项。对于您的接口规则,您可以替换:

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


最后,您发布的代码的实际问题是,您使用的是
|
操作符,这是一个简单的表单。MatchFirst将按顺序尝试给定的选项,并返回匹配的第一个选项的结果。如果改为使用,其缩写形式为
^
运算符,然后它将尝试所有选项并返回最长匹配的选项。

尝试重新排序
rule=zoneRule | hostRule | interfaceRule | interfaceRule | interfaceRule | interfaceRule | firewallRule | routerRule | endRule
rule=zoneRule | hostRule | interfaceRule | interfaceRule | interfaceRule | firewallRule | firewallRule | endRule 124。另外,如果可能的话,试着使
interface2
更具体一些,比如
interfaceRule2=interface+interfaceeid+address+CaselessLiteral('nat')
interfaceRule2=interface+interfaceeid+address+oneOf(“nat ext ipv6 other1 other2”)
。还可以查看2.1.5版本,包括IPv4和IPv6地址的
pyparsing\u common
定义。
Optional
对于这个问题是一个很好的建议,但可能需要比
word
更具体,因为它匹配任何字母组,这可能包括下一个防火墙规则的主要
接口
。非常感谢您提供的大量解决方案,您已经尝试了所有解决方案,并且重新排序规则完成了它的工作,事实上,根据上面的评论,使用可选(word)替换为单词“接口”,因此使用ClasslessLiteral('nat')是解决问题的一种方法。唯一的问题是,如果我遇到超过“nat”,我将不得不手动添加这些文本。但问题得到了回答。非常感谢你。感谢你的帮助!
interfaceRule = interface + interfaceid + address + Optional(word)