适用于华为华三交换机防火墙配置文件格式
增加解析汇总 ACL ,方便查看 ACL应用在哪些接口及ACL规则信息
用于定时备份设备配置文件后,对配置文件的变化做出分析。
对运行状态配置和保存配置进行对比,发现差异配置。
支持
文本文件配置文件:vrpcfg.cfg
压缩包配置文件:vrpcfg.zip(自动下载交换机/防火墙配置文件可参考其他文章)
dis cu 命令查询结果配置(自动登录并执行命令,保存回显结果可参考其他文章)
#!/usr/local/python3/bin/python3
# -*- coding: utf8 -*-
import sys, time, os, zipfile
## 终端显示颜色
if os.name == 'nt': # Windows
import ctypes,sys
STD_OUTPUT_HANDLE = -11
# Windows CMD命令行 字体颜色定义 text colors
黑字 = 0x00 # black.
FOREGROUND_DARKBLUE = 0x01 # dark blue.
FOREGROUND_DARKGREEN = 0x02 # dark green.
FOREGROUND_DARKSKYBLUE = 0x03 # dark skyblue.
FOREGROUND_DARKRED = 0x04 # dark red.
FOREGROUND_DARKPINK = 0x05 # dark pink.
FOREGROUND_DARKYELLOW = 0x06 # dark yellow.
FOREGROUND_DARKWHITE = 0x07 # dark white.
FOREGROUND_DARKGRAY = 0x08 # dark gray.
FOREGROUND_BLUE = 0x09 # blue.
FOREGROUND_GREEN = 0x0a # green.
FOREGROUND_SKYBLUE = 0x0b # skyblue.
FOREGROUND_RED = 0x0c # red.
FOREGROUND_PINK = 0x0d # pink.
FOREGROUND_YELLOW = 0x0e # yellow.
FOREGROUND_WHITE = 0x0f # white.
std_out_handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
def set_cmd_text_color(color, handle=std_out_handle):
Bool = ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
return Bool
def resetColor():
set_cmd_text_color(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
def 打印_黑(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(黑字)
sys.stdout.write(TEXT+'\n')
resetColor()
def 打印_红(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(FOREGROUND_RED)
sys.stdout.write(TEXT+'\n')
resetColor()
def 打印_绿(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(FOREGROUND_GREEN)
sys.stdout.write(TEXT+'\n')
resetColor()
def 打印_黄(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(FOREGROUND_YELLOW)
sys.stdout.write(TEXT+'\n')
resetColor()
def 打印_蓝(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(FOREGROUND_BLUE)
sys.stdout.write(TEXT+'\n')
resetColor()
def 打印_紫(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(FOREGROUND_PINK)
sys.stdout.write(TEXT+'\n')
resetColor()
def 打印_青(TEXT, SHOW=1):
if SHOW == 1:
set_cmd_text_color(FOREGROUND_SKYBLUE)
sys.stdout.write(TEXT+'\n')
resetColor()
elif os.name == 'posix': # Linux
def 打印_黑(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;30;1m{TEXT}\033[0m")
def 打印_红(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;31;1m{TEXT}\033[0m")
def 打印_绿(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;32;1m{TEXT}\033[0m")
def 打印_黄(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;33;1m{TEXT}\033[0m")
def 打印_蓝(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;34;1m{TEXT}\033[0m")
def 打印_紫(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;35;1m{TEXT}\033[0m")
def 打印_青(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;36;1m{TEXT}\033[0m")
def 打印_白(TEXT, SHOW=1):
if SHOW == 1:
print(f"\033[0;37;1m{TEXT}\033[0m")
## 读取网络设备上下载的 startup.cfg 配置文件(文本文件)
## 读取 dis cu 查询配置保存下来的文本文件
def 读取文本文件内容(FILE_PATH):
L_编码 = ['UTF8', 'GB2312', 'GBK', 'BIG5']
TEXT = None
if os.path.isfile(FILE_PATH):
for 编码 in L_编码:
try:
#print(f"尝试 {编码}")
f = open(FILE_PATH, 'r', encoding=编码)
TEXT = f.read()
except Exception as e:
f.close()
#打印_红(f"{编码}编码读取{FILE_PATH}失败{e}")
else:
f.close()
#print(f"成功 TEXT={TEXT}")
return(TEXT)
else:
打印_红(f"ERROR 文件 {FILE_PATH} 不存在")
return(TEXT)
打印_红(f"ERROR 文件 {FILE_PATH} 字符编码解码失败,超出{L_编码}范围")
return(TEXT)
## 网络设备上下载的配置文件有压缩包类型,如:vrpcfg.zip 里面就一个配置文本文件 vrpcfg.cfg
def 读取ZIP中第一个文件(FILE_PATH):
TEXT = None
if os.path.isfile(FILE_PATH):
if zipfile.is_zipfile(FILE_PATH):
try:
f = zipfile.ZipFile(FILE_PATH)
except Exception as e:
ERROR = f'ERROR zipfile 打开 {FILE_PATH} 失败 {e}'
打印_红(ERROR)
return()
else:
for i in f.namelist():
#print("ZIP内文件", i)
文件名, 扩展名 = os.path.splitext(i)
#print(文件名, 扩展名)
if i.endswith('/'):
#print(f"目录 {i}")
pass
else:
#print(f"文件 {i}")
try:
DATA = f.open(i)
except Exception as e:
ERROR = f'ERROR 打开 {i} 失败 {e}'
print(ERROR)
else:
TEXT = DATA.read().decode('GB2312') # 一般是 GB2312
#print("TEXT", TEXT)
break
else:
打印_红(f"ERROR {FILE_PATH} 不是ZIP格式文件")
else:
打印_红(f"ERROR {FILE_PATH} 不存在或不是文件")
return(TEXT)
def 前置空格数(TEXT):
N = 0
for i in TEXT:
if i == ' ':
N += 1
else:
break
return(N)
def 配置文本分段分行(TEXT_CONF, SHOW=0):
LL_CONF = []
LL_配置行 = [[j for j in i.split('\r')] for i in TEXT_CONF.split('\n')] # 以换行符分段
#打印_蓝(f"换行符分段 LL_配置行={LL_配置行}", SHOW)
L_配置段 = []
for L_配置行 in LL_配置行:
#打印_红(f"{L_配置行}", SHOW)
for 配置行 in L_配置行:
if 配置行.strip() != '': # 忽略空配置行
if 配置行 == '#': # 遇到分段符号'#'进行分段保存
if L_配置段 != []:
LL_CONF.append(L_配置段)
L_配置段 = [] # 重置为空列表
else:
L_配置段.append(配置行)
#打印_绿(f"{LL_CONF}", SHOW)
#for i in LL_CONF:
# 打印_蓝(f"{i}\n", SHOW)
return(LL_CONF)
def 配置行转配置信息字典(LL_CONF, SHOW=0):
打印_红("[配置行转配置信息字典]", SHOW)
D_NET_CONF = {'GLOBAL':[]}
for L_配置段 in LL_CONF:
打印_红(f"L_配置段={L_配置段}", SHOW)
KEY = 'GLOBAL'
for TEXT_配置行 in L_配置段:
配置行前置空格数 = 前置空格数(TEXT_配置行)
打印_蓝(f" 前置空格数={配置行前置空格数} TEXT_配置行={TEXT_配置行}", SHOW)
if 配置行前置空格数 == 0:
KEY = TEXT_配置行 # 更新KEY
if KEY not in D_NET_CONF:
D_NET_CONF[KEY] = []
打印_绿(f" KEY={KEY}", SHOW)
else:
D_NET_CONF[KEY].append(TEXT_配置行)
打印_绿(f" D_NET_CONF[{KEY}].append({TEXT_配置行})", SHOW)
return(D_NET_CONF)
def 转换网络TXT配置文件(FILE_CONF_PATH, SHOW=0):
D_NET_CONF = {}
TEXT_CONF = 读取文本文件内容(FILE_CONF_PATH)
打印_黄(f"TEXT_CONF={TEXT_CONF}", SHOW)
if TEXT_CONF != None:
LL_CONF = 配置文本分段分行(TEXT_CONF, SHOW)
D_NET_CONF = 配置行转配置信息字典(LL_CONF, SHOW)
return(D_NET_CONF)
def 转换网络ZIP配置文件(FILE_CONF_PATH, SHOW=0):
D_NET_CONF = {}
TEXT_CONF = 读取ZIP中第一个文件(FILE_CONF_PATH)
打印_黄(f"TEXT_CONF={TEXT_CONF}", SHOW)
if TEXT_CONF != None:
LL_CONF = 配置文本分段分行(TEXT_CONF, SHOW)
D_NET_CONF = 配置行转配置信息字典(LL_CONF, SHOW)
return(D_NET_CONF)
def 网络配置文件转配置字典(FILE_CONF_PATH, SHOW=0):
FILE_NAME = os.path.basename(FILE_CONF_PATH)
SP = FILE_NAME.split('.')
if SP != [] and SP[-1].lower() == 'zip':
D_NET_CONF = 转换网络ZIP配置文件(FILE_CONF_PATH, SHOW)
else:
D_NET_CONF = 转换网络TXT配置文件(FILE_CONF_PATH, SHOW)
配置字典再加工(D_NET_CONF, SHOW)
return(D_NET_CONF)
def SAVE_TEXT(TEXT, SAVE_PATH, SHOW=1):
try:
f = open(SAVE_PATH, 'w')
BYTES = f.write(TEXT)
f.close()
except Exception as e:
打印_红(f"{SAVE_PATH} X", SHOW)
else:
打印_绿(f"{SAVE_PATH} V {BYTES}", SHOW)
def 对比配置字典(D_OLD, D_NEW, SHOW=1):
TEXT_对比结果 = ''
if D_OLD != {} and D_NEW != {}:
## 对比新旧配置项是否有新增或删除
P_KEY_D_OLD = set([K for K in D_OLD]) # 旧配置项
P_KEY_D_NEW = set([K for K in D_NEW]) # 新配置项
#print(f"P_KEY_D_OLD={P_KEY_D_OLD}")
#print(f"P_KEY_D_NEW={P_KEY_D_NEW}")
P_KEY_OLD_独有 = P_KEY_D_OLD - P_KEY_D_NEW
P_KEY_NEW_独有 = P_KEY_D_NEW - P_KEY_D_OLD
if P_KEY_OLD_独有 == P_KEY_NEW_独有 == set():
P_KEY_共有 = P_KEY_D_OLD
INFO = f" [新旧配置项] 一致"
TEXT_对比结果 += INFO+'\n'
打印_绿(INFO, SHOW)
else:
P_KEY_共有 = P_KEY_D_OLD & P_KEY_D_NEW
INFO = f" [新旧配置项] 不同\n P_KEY_OLD_独有 {P_KEY_OLD_独有}\n P_KEY_NEW_独有 {P_KEY_NEW_独有}"
打印_黄(INFO, SHOW)
TEXT_对比结果 += INFO+'\n'
for KEY in P_KEY_OLD_独有:
INFO = f" [删除配置项] {KEY} 【配置项内容】 {D_OLD[KEY]}"
TEXT_对比结果 += INFO+'\n'
打印_蓝(INFO, SHOW)
for KEY in P_KEY_NEW_独有:
INFO = f" [新增配置项] {KEY} 【配置项内容】 {D_NEW[KEY]}"
TEXT_对比结果 += INFO+'\n'
打印_青(INFO, SHOW)
## 相同配置项对比配置内容是否有变化
for KEY in P_KEY_共有:
if D_OLD[KEY] != D_NEW[KEY]:
P_OLD_配置行 = set(D_OLD[KEY])
P_NEW_配置行 = set(D_NEW[KEY])
if P_OLD_配置行 == P_NEW_配置行:
INFO = f" [配置项] {KEY} 配置行内容有重复"
TEXT_对比结果 += INFO+'\n'
打印_红(INFO, SHOW)
else:
INFO = f" [变化配置项] {KEY}"
TEXT_对比结果 += INFO+'\n'
打印_红(INFO, SHOW)
for i in P_OLD_配置行-P_NEW_配置行:
INFO = f" [DEL] {i}"
TEXT_对比结果 += INFO+'\n'
打印_蓝(INFO, SHOW)
for i in P_NEW_配置行-P_OLD_配置行:
INFO = f" [ADD] {i}"
TEXT_对比结果 += INFO+'\n'
打印_青(INFO, SHOW)
else:
if D_OLD == {}:
INFO = " D_OLD 无有效内容"
TEXT_对比结果 += INFO+'\n'
打印_红(INFO)
if D_NEW == {}:
INFO = " D_NEW 无有效内容"
TEXT_对比结果 += INFO+'\n'
打印_红(INFO)
return(TEXT_对比结果)
def 载入字典形式文本文件(FILE_PATH):
D = {}
if os.path.isfile(FILE_PATH):
try:
f = open(FILE_PATH, 'r')
TEXT = f.read()
f.close()
except Exception as e:
打印_红(f"读取文件 {FILE_PATH} 失败 {e}")
else:
D = eval(TEXT)
else:
打印_红(f" ERROR 文件{FILE_PATH}不存在")
return(D)
def 防火墙安全规则转字典(LL_CONF, SHOW=0):
打印_红("[防火墙安全规则转字典]", SHOW)
D_security_policy = {'security-policy':[]}
KEY = 'security-policy'
for TEXT_配置行 in LL_CONF:
配置行前置空格数 = 前置空格数(TEXT_配置行)
打印_蓝(f" 前置空格数={配置行前置空格数} TEXT_配置行={TEXT_配置行}", SHOW)
if 配置行前置空格数 == 1:
KEY = ('security-policy', TEXT_配置行) # 更新KEY
if KEY not in D_security_policy:
D_security_policy[KEY] = []
打印_绿(f" KEY={KEY}", SHOW)
else:
D_security_policy[KEY].append(TEXT_配置行)
打印_绿(f" D_security_policy[{KEY}].append({TEXT_配置行})", SHOW)
return(D_security_policy)
def AAA用户信息转字典(LL_CONF, SHOW=0):
打印_红("[AAA用户信息转字典]", SHOW)
D_AAA = {'aaa':[]}
KEY = 'aaa'
for TEXT_配置行 in LL_CONF:
配置行前置空格数 = 前置空格数(TEXT_配置行)
打印_蓝(f" 前置空格数={配置行前置空格数} TEXT_配置行={TEXT_配置行}", SHOW)
if 配置行前置空格数 == 1:
KEY = ('aaa', TEXT_配置行) # 更新KEY
if KEY not in D_AAA:
D_AAA[KEY] = []
打印_绿(f" KEY={KEY}", SHOW)
else:
D_AAA[KEY].append(TEXT_配置行)
打印_绿(f" D_AAA[{KEY}].append({TEXT_配置行})", SHOW)
return(D_AAA)
def 配置字典再加工(D_NET_CONF, SHOW=0):
# 删除一些无用信息(注释、查询命令等)
for K in [i for i in D_NET_CONF]:
if K == 'dis cu' or K[0] in ('*', '<', '[', '\x00'):
del D_NET_CONF[K]
打印_黄(f" 删除 {K}", SHOW)
#else:
# 打印_绿(f" 保留 {K}", SHOW)
# 删除空全局配置
if 'GLOBAL' in D_NET_CONF and D_NET_CONF['GLOBAL'] == []:
del D_NET_CONF['GLOBAL']
打印_黄(f" 删除 空 D_NET_CONF['GLOBAL']", SHOW)
# 进一步细分,整理防火墙安全策略信息,方便对比策略变化
if 'security-policy' in D_NET_CONF:
#print(D_NET_CONF['security-policy'])
LL_CONF = D_NET_CONF['security-policy']
D_security_policy = 防火墙安全规则转字典(LL_CONF, SHOW)
del D_NET_CONF['security-policy']
for K in D_security_policy:
D_NET_CONF[K] = D_security_policy[K]
# 进一步细分,整理aaa用户信息,方便对比用户信息变化
if 'aaa' in D_NET_CONF:
LL_CONF = D_NET_CONF['aaa']
D_AAA = AAA用户信息转字典(LL_CONF, SHOW)
del D_NET_CONF['aaa']
for K in D_AAA:
D_NET_CONF[K] = D_AAA[K]
def TEST_换行符分段():
TEXT = 'aa\r\nbb\ncc\rdd\n\ne\r\rf\n g g \n'
print(TEXT)
print("\\r ", TEXT.split('\r'))
print("\\n ", TEXT.split('\n'))
print("\\r\\n", TEXT.split('\r\n'))
print("分段 先\\r 再\\n")
Lr = [i for i in TEXT.split('\r')]
print("Lr", Lr)
LL = [[j for j in i.split('\n')] for i in TEXT.split('\r')]
print("LL", LL)
print()
print("分段 先\\n 再\\r")
Ln = [i for i in TEXT.split('\n')]
print("Ln", Ln)
LL = [[j for j in i.split('\r')] for i in TEXT.split('\n')]
print("LL", LL)
for i in LL:
for j in i:
print(j)
for i in LL:
for j in i:
if j != '':
print(j)
## ACL 解析
def 配置字典转ACL信息字典(D_NET_CONF, SHOW=0):
D_ACL_INFO = {}
#{
# (ACL_ID, ACL_NAME):{
# 'RULE':['RULE 明细', ],
# '规则应用信息:[{
# 'TYPE': '接口或其他'
# 'CONF': '规则应用配置,进出方向等'
# 'DESC': '备注',
# }, {}]
# },
# (ACL_ID, ACL_NAME):{},
# },
#}
for KEY in D_NET_CONF:
if type(KEY) == str:
SP_KEY = KEY.split()
if SP_KEY != [] and SP_KEY[0] == 'acl':
打印_紫(f"ACL : {KEY}", SHOW)
if 'number' in SP_KEY:
ACL_ID = SP_KEY[SP_KEY.index('number')+1]
else:
ACL_ID = ''
if 'name' in SP_KEY:
ACL_NAME = SP_KEY[SP_KEY.index('name')+1]
else:
ACL_NAME = ''
D_ACL_INFO[(ACL_ID,ACL_NAME)] = {'RULE':D_NET_CONF[KEY], '规则应用信息':[]}
#打印_红(f"D_ACL_INFO={D_ACL_INFO}")
## 解析ACL在接口上的应用信息
for KEY in D_NET_CONF:
打印_紫(f"KEY={KEY}", SHOW)
if type(KEY) == str:
SP_KEY = KEY.split()
if SP_KEY != [] and SP_KEY[0] == 'interface':
打印_蓝(f"interface : {KEY}", SHOW)
for 接口配置行 in D_NET_CONF[KEY]:
L_SP_接口配置 = 接口配置行.split()
if 'packet-filter' in L_SP_接口配置 or 'traffic-filter' in L_SP_接口配置:
for ACL_ID,ACL_NAME in D_ACL_INFO:
if ACL_ID in L_SP_接口配置 or ACL_NAME in L_SP_接口配置:
打印_蓝(f"{(ACL_ID,ACL_NAME)}", SHOW)
L_接口备注 = [i for i in D_NET_CONF[KEY] if 'description' in i.split()]
if L_接口备注 != []:
接口备注 = L_接口备注[0].strip()
else:
接口备注 = '无'
打印_绿(f" {KEY:22s} {接口配置行:33s} | {接口备注}", SHOW)
D_ACL_INFO[(ACL_ID,ACL_NAME)]['规则应用信息'].append({'TYPE':KEY, 'CONF':接口配置行.strip(), 'DESC':接口备注})
for RULE_TEXT in D_ACL_INFO[(ACL_ID,ACL_NAME)]['RULE']:
打印_青(f" {RULE_TEXT}", SHOW)
elif SP_KEY != [] and SP_KEY[0] == 'acl':
打印_红(f"ACL : {KEY} PASS", SHOW)
else:
## ACL 应用在顶级配置上
打印_黄(f"Other : {KEY}", SHOW)
for ACL_ID,ACL_NAME in D_ACL_INFO:
if ACL_ID in SP_KEY or ACL_NAME in SP_KEY:
if D_NET_CONF[KEY] == []:
CONF = ''
else:
CONF = str(D_NET_CONF[KEY])
DESC = ''
打印_蓝(f"{(ACL_ID,ACL_NAME)}", SHOW)
打印_绿(f" {KEY:22s} {CONF:33s} |", SHOW)
D_ACL_INFO[(ACL_ID,ACL_NAME)]['规则应用信息'].append({'TYPE':KEY, 'CONF':CONF, 'DESC':DESC})
else:
for 配置行 in D_NET_CONF[KEY]:
L_SP_配置行 = 配置行.split()
if ACL_ID in L_SP_配置行 or ACL_NAME in L_SP_配置行:
CONF = 配置行.strip()
DESC = ''
打印_蓝(f"{(ACL_ID,ACL_NAME)}", SHOW)
打印_绿(f" {KEY:22s} {CONF:33s} |", SHOW)
D_ACL_INFO[(ACL_ID,ACL_NAME)]['规则应用信息'].append({'TYPE':KEY, 'CONF':CONF, 'DESC':DESC})
return(D_ACL_INFO)
def 配置文件转ACL信息字典(FILE_CONF_PATH, SHOW=0):
D_NET_CONF = 网络配置文件转配置字典(FILE_CONF_PATH, SHOW)
D_ACL_INFO = 配置字典转ACL信息字典(D_NET_CONF, SHOW)
return(D_ACL_INFO)
def ACL信息字典转文本(D_ACL_INFO):
换行符 = '\n'
TEXT = ''
for K in D_ACL_INFO:
TEXT += f" ACL={K}{换行符}"
TEXT += f" 规则应用信息{换行符}"
for 规则应用信息 in D_ACL_INFO[K]['规则应用信息']:
TEXT += f" {规则应用信息}{换行符}"
TEXT += f" ACL规则{换行符}"
for RULE in D_ACL_INFO[K]['RULE']:
TEXT += f" {RULE}{换行符}"
TEXT += 换行符
return(TEXT)
## 测试
if __name__ == '__main__':
def 测试_文本配置文件(FILE_CONF_PATH):
D_NET_CONF = 转换网络TXT配置文件(FILE_CONF_PATH, SHOW=1)
for K in D_NET_CONF:
打印_红(f"{K}")
打印_蓝(f" {D_NET_CONF[K]}")
#FILE_CONF_PATH = 'E:\\TEST\\A.down_run_txt'
#测试_文本配置文件(FILE_CONF_PATH)
def 测试_压缩包配置文件(FILE_CONF_PATH):
D_NET_CONF = 转换网络ZIP配置文件(FILE_CONF_PATH, SHOW=1)
for K in D_NET_CONF:
打印_红(f"{K}")
打印_蓝(f" {D_NET_CONF[K]}")
#FILE_CONF_PATH = 'E:\\TEST\\A_vrpcfg.zip'
#测试_压缩包配置文件(FILE_CONF_PATH)
def 测试_对比两个配置文件差异(FILE_CONF_OLD_PATH, FILE_CONF_NEW_PATH):
D_NET_CONF_OLD = 网络配置文件转配置字典(FILE_CONF_OLD_PATH, SHOW=0)
D_NET_CONF_NEW = 网络配置文件转配置字典(FILE_CONF_NEW_PATH, SHOW=0)
打印_蓝(f"OLD {FILE_CONF_OLD_PATH}")
打印_青(f"NEW {FILE_CONF_NEW_PATH}")
TEXT_对比结果 = 对比配置字典(D_NET_CONF_OLD, D_NET_CONF_NEW, SHOW=1)
打印_紫(TEXT_对比结果)
#FILE_CONF_OLD_PATH = 'E:\\TEST\\A_vrpcfg.zip'
#FILE_CONF_NEW_PATH = 'E:\\TEST\\A.down_run_txt'
#测试_对比两个配置文件差异(FILE_CONF_OLD_PATH, FILE_CONF_NEW_PATH)
def 测试_解析配置后保存为字典类型文本文件(FILE_CONF_PATH, SAVE_PATH):
D_NET_CONF = 网络配置文件转配置字典(FILE_CONF_PATH, SHOW=1)
SAVE_TEXT(f"{D_NET_CONF}", SAVE_PATH, SHOW=1)
#FILE_CONF_PATH = 'E:\\TEST\\A_vrpcfg.zip'
#SAVE_PATH = 'E:\\TEST\\A_vrpcfg.zip.cfg_dict_txt'
#测试_解析配置后保存为字典类型文本文件(FILE_CONF_PATH, SAVE_PATH)
def 测试_读取字典形式保存的配置文件(FILE_PATH):
D_NET_CONF = 载入字典形式文本文件(FILE_PATH)
for K in D_NET_CONF:
打印_红(f"{K}")
打印_蓝(f" {D_NET_CONF[K]}")
#FILE_PATH = 'E:\\TEST\\A_vrpcfg.zip.cfg_dict_txt'
#测试_读取字典形式保存的配置文件(FILE_PATH)
## 交换机 ACL 信息整理
#FILE_CONF_PATH = f'E:\\TEST\\A_vrpcfg.zip'
#D_ACL_INFO = 配置文件转ACL信息字典(FILE_CONF_PATH, SHOW=0)
#TEXT = ACL信息字典转文本(D_ACL_INFO)
#打印_黄(TEXT)