使用Python读取fortigate配置文件

时间:2011-09-26 08:18:00

标签: python list configparser

对于真正长期存在的问题的猜测。

我正在尝试读取配置文件并获取规则列表。 我曾尝试使用ConfigParser来执行此操作,但它不是标准配置文件。 该文件不包含节标题,也没有标记。

即。

  

配置部分a    把东西设置成别的东西
   config subsection a    把它设置为那个    下一个    结束

     

配置防火墙策略
   编辑76
   设置srcintf“那里”
   设置dstintf“这里”
   设置srcaddr“全部”
   设置dstaddr“全部”
   设定行动接受
   设定时间表“总是”
   设置服务“TCP_5600”
   下一个    编辑77
   设置srcintf“这里”
   设置dstintf“那里”
   设置srcaddr“全部”
   设置dstaddr“全部”
   设定行动接受
   设定时间表“总是”
   设置服务“PING”
   下一个    端

由于我无法弄清楚如何让ConfigParser工作,我以为我会尝试迭代文件,不幸的是我没有太多的编程技巧所以我卡住了。 我真的认为我让它变得比它应该更复杂。 这是我写的代码;

class Parser(object):

    def __init__(self):
        self.config_section = ""
        self.config_header = ""
        self.section_list = []
        self.header_list = []

    def parse_config(self, fields): # Create a new section
        new_list = []
        self.config_section = " ".join(fields)
        new_list.append(self.config_section)

        if self.section_list: # Create a sub section
            self.section_list[-1].append(new_list)
        else: self.section_list.append(new_list)

    def parse_edit(self, line): # Create a new header
        self.config_header = line[0]
        self.header_list.append(self.config_header)

        self.section_list[-1].append(self.header_list)  

    def parse_set(self, line): # Key and values
        key_value = {}

        key = line[0]
        values = line[1:]
        key_value[key] = values

        if self.header_list:
            self.header_list.append(key_value)
        else: self.section_list[-1].append(key_value)

    def parse_next(self, line): # Close the header
        self.config_header = []

    def parse_end(self, line): # Close the section
        self.config_section = []

    def parse_file(self, path):
        with open(path) as f:
            for line in f:

                # Clean up the fields and remove unused lines.            
                fields = line.replace('"', '').strip().split(" ")

                if fields[0] == "set":
                    pass
                elif fields[0] == "end":
                    pass
                elif fields[0] == "edit":
                    pass
                elif fields[0] == "config":
                    pass
                elif fields[0] == "next":
                    pass
                else: continue

                # fetch and call method.
                method = fields[0]
                parse_method = "parse_" + method

                getattr(Parser, parse_method)(self, fields[1:])
                return self.section_list

config = Parser().parse_file('test_config.txt')

print config

我正在寻找的输出类似于以下内容;

  

[['section a',{'something':'to something else'},['subsection a',{'this':'to that'}]],['防火墙政策',['76 ',{'srcintf':'有'},{'dstintf':'这里'} {等等} {等等}}]]

这就是我得到的

  

[['section a']]

修改

我已经改变了上述内容以反映我目前的位置。 我仍有问题得到我期望的输出。我似乎无法将清单正确。

4 个答案:

答案 0 :(得分:1)

 class Parser(object):

     def __init__(self):
         self.my_section = 0
         self.flag_section = False
         # ...

    def parse_config(self, fields):
         self.my_section += 1
         # go on with fields
         # ...
         self.flag_section = True

     def parse_edit(self, line):
         ...

     def parse_set(self, line):
         ...

     def parse_end(self, line):
         ...

     def parse_file(self, path):
         with open(path) as f:
              for line in f:
                  fields = f.strip().split(" ")

                  method = fields[0]
                  # fetch and call method
                  getattr(Parser, "parse_" + method)(self, fields[1:])

答案 1 :(得分:1)

我为那些在尝试解析Fortigate配置文件时从Google首次来到这里的人发布了我的答案! 我根据自己的需要改写了我在这里找到的东西,并且效果很好。

from collections import defaultdict
from pprint import pprint
import sys

f = lambda: defaultdict(f)

def getFromDict(dataDict, mapList):
    return reduce(lambda d, k: d[k], mapList, dataDict)

def setInDict(dataDict, mapList, value):
    getFromDict(dataDict, mapList[:-1])[mapList[-1]] = value    

class Parser(object):

    def __init__(self):
        self.config_header = []
        self.section_dict = defaultdict(f)     

    def parse_config(self, fields): # Create a new section
        self.config_header.append(" ".join(fields))

    def parse_edit(self, line): # Create a new header
        self.config_header.append(line[0])

    def parse_set(self, line): # Key and values
        key = line[0]
        values = " ".join(line[1:])
        headers= self.config_header+[key]
        setInDict(self.section_dict,headers,values)

    def parse_next(self, line): # Close the header
        self.config_header.pop()

    def parse_end(self, line): # Close the section
        self.config_header.pop()

    def parse_file(self, path):          
        with open(path) as f:
            gen_lines = (line.rstrip() for line in f if line.strip())
            for line in gen_lines:
               # pprint(dict(self.section_dict))
                # Clean up the fields and remove unused lines.            
                fields = line.replace('"', '').strip().split(" ")

                valid_fields= ["set","end","edit","config","next"]
                if fields[0] in valid_fields:
                    method = fields[0]
                    # fetch and call method
                    getattr(Parser, "parse_" + method)(self, fields[1:])

        return self.section_dict

config = Parser().parse_file('FGT02_20130308.conf')

print config["system admin"]["admin"]["dashboard-tabs"]["1"]["name"]
print config["firewall address"]["ftp.fr.debian.org"]["type"]

答案 2 :(得分:0)

我不知道这是否对你有帮助,但它确实对我有用:http://wiki.python.org/moin/ConfigParserExamples

玩得开心!

答案 3 :(得分:0)

我会以更简单的方式做到这一点:

flagSection = False
flagSub = False

mySection = 0
mySubsection = 0
myItem = 0

with open('d:/config.txt', 'r') as f:
    gen_lines = (line.rstrip() for line in f if line.strip())

    for line in gen_lines:

            if line[0:7]=='config ':
                mySection = mySection + 1
                newLine = line[7:]
                # Create a new section
                # Mark section as open
                flagSection == True

            elif line[0:5]=='edit '):
                mySubsection = mySubsection + 1
                newLine = line[5:]
                # Create a new sub-section
                # Mark subsection as open
                flagSub == true

            elif line[0:4]=='set '):
                myItem = myItem + 1
                name, value = x.split(' ',2)[1:]
                # Add to whatever is open

            elif line=='end':
                # If subsection = open then close and goto end
                if flagSub:
                # Or if section = open then close and goto end
                elif flagSection:
                # :End
                continue

指令gen_lines = (line.rstrip() for line in f if line.strip()) 创建一个非空行的生成器(感谢测试if line.strip()),没有换行符,右边没有空格(感谢line.rstrip()

如果我想了解您想要使用名称,值以及使用if line=='end'打开的部分中执行的操作的更多信息,我可以使用正则表达式提出代码。

修改

from time import clock

n = 1000000

print 'Measuring times with clock()'

te = clock()
for i in xrange(n):
    x = ('abcdfafdf'[:3] == 'end')
print clock()-te,
print "\tx = ('abcdfafdf'[:3] == 'end')"


te = clock()
for i in xrange(n):
    x = 'abcdfafdf'.startswith('end')
print clock()-te,
print "\tx = 'abcdfafdf'.startswith('end')"



print '\nMeasuring times with timeit module'

import timeit

ti = timeit.repeat("x = ('abcdfafdf'[:3] == 'end')",repeat=10,number = n)
print min(ti),
print "\tx = ('abcdfafdf'[:3] == 'end')"

to = timeit.repeat("x = 'abcdfafdf'.startswith('end')",repeat=10,number = n)
print min(to),
print "\tx = 'abcdfafdf'.startswith('end')"

结果:

Measuring times with clock()
0.543445605517  x = ('abcdfafdf'[:3] == 'end')
1.08590449345   x = 'abcdfafdf'.startswith('end')

Measuring times with timeit module
0.294152748464  x = ('abcdfafdf'[:3] == 'end')
0.901923289133  x = 'abcdfafdf'.startswith('end')

timieit 的时间比使用 clock()的时间要小,因为在程序运行时GC已被拔掉?无论如何,使用 clock() timeit 模块,执行 startswith()比切片花费更多时间。