python - Python - 递归字符串查找
问题描述
我正在尝试解析 cisco config 防火墙输出。我正在尝试递归查找嵌套object-group
,直到找到每个的 IPobject-group
这是一个场景示例:
asa# sh object-group id aws_all_critical_vpcs
object-group network aws_all_critical_vpcs
group-object aws_criticalprd_us_west_2_app_db
group-object aws_critical_us_west_2_app_db
group-object aws_criticalprd_us_east_1_app_db
group-object aws_critical_us_east_1_app_db
group-object aws_criticalprd_eu_west_1_app_db
group-object aws_critical_eu_west_1_app_db
group-object aws_criticalprd_eu_central_1_app_db
group-object aws_critical_eu_central_1_app_db
asa# sh object-group id aws_criticalprd_us_west_2_app_db
object-group network aws_criticalprd_us_west_2_app_db
group-object aws_criticalprd_us_west_2_app
group-object aws_criticalprd_us_west_2_db
asa# sh object-group id aws_criticalprd_us_west_2_app
object-group network aws_criticalprd_us_west_2_app
network-object 10.159.160.0 255.255.248.0
asa# sh object-group id aws_criticalprd_us_west_2_db
object-group network aws_criticalprd_us_west_2_db
network-object 10.159.168.0 255.255.248.0
我已经设法让某些东西工作了,但是由于硬编码,代码可以挖掘出嵌套级别的限制if/else
for e in og_content:
if 'group-object' not in e:
new_og_content.append(e)
elif 'group-object' in e:
new_og_content.append(e)
for k in find_the_lines(og_list,e.split()[1]):
new_og_content.append(k)
if 'network-object' in k:
new_og_content.append(' ' + k)
elif 'group-object' in k:
for z in find_the_lines(og_list,k.split()[1]):
if 'network-object' in z:
new_og_content.append(' ' + z)
输出看起来不错,这正是我想要的,但我想要更聪明的东西,它对嵌套对象组的查找数量没有限制。这是一个输出示例:
group-object aws_criticalprd_us_west_2_app_db
group-object aws_criticalprd_us_west_2_app
network-object 10.159.160.0 255.255.248.0
group-object aws_criticalprd_us_west_2_db
network-object 10.159.168.0 255.255.248.0
group-object aws_critical_us_west_2_app_db
group-object aws_critical_us_west_2_app
network-object 10.159.192.0 255.255.248.0
group-object aws_critical_us_west_2_db
...etc...
有什么建议吗?
解决方案
TTP 可以帮助解析这些数据并使用 python 函数对其进行转换,这里是示例代码:
from ttp import ttp
template = """
<input load="text">
asa# sh object-group id aws_criticalprd_us_west_2_app
object-group network aws_criticalprd_us_west_2_app
network-object 10.159.160.0 255.255.248.0
network-object 10.159.161.0 255.255.248.0
asa# sh object-group id aws_criticalprd_us_west_2_db
object-group network aws_criticalprd_us_west_2_db
network-object 10.159.168.0 255.255.248.0
asa# sh object-group id aws_criticalprd_us_west_2_app_db
object-group network aws_criticalprd_us_west_2_app_db
group-object aws_criticalprd_us_west_2_app
group-object aws_criticalprd_us_west_2_db
asa# sh object-group id aws_all_critical_vpcs
object-group network aws_all_critical_vpcs
group-object aws_criticalprd_us_west_2_app_db
group-object aws_critical_us_west_2_app_db
group-object aws_criticalprd_us_east_1_app_db
group-object aws_critical_us_east_1_app_db
group-object aws_criticalprd_eu_west_1_app_db
group-object aws_critical_eu_west_1_app_db
group-object aws_criticalprd_eu_central_1_app_db
group-object aws_critical_eu_central_1_app_db
</input>
<group name="{{ network_obj }}">
object-group network {{ network_obj }}
group-object {{ group_obj | to_list | joinmatches }}
network-object {{ subnet | PHRASE | to_list | joinmatches }}
</group>
<macro>
def lookup_objects(data, name=""):
# kick recursion off
if name == "":
return {key: lookup_objects(data, name=key) for key in data[0].keys()}
# if name in data, check if it contains subnet or run recursion for group_obj:
elif name in data[0]:
if "subnet" in data[0][name]:
return data[0][name]["subnet"]
return {
group_obj: lookup_objects(data, name=group_obj)
for group_obj in data[0][name].get("group_obj", [])
}
else:
return {}
</macro>
<output macro="lookup_objects"/>
"""
parser = ttp(template=template)
parser.parse()
print(parser.result(format="json")[0])
输出将是:
{
"aws_all_critical_vpcs": {
"aws_critical_eu_central_1_app_db": {},
"aws_critical_eu_west_1_app_db": {},
"aws_critical_us_east_1_app_db": {},
"aws_critical_us_west_2_app_db": {},
"aws_criticalprd_eu_central_1_app_db": {},
"aws_criticalprd_eu_west_1_app_db": {},
"aws_criticalprd_us_east_1_app_db": {},
"aws_criticalprd_us_west_2_app_db": {
"aws_criticalprd_us_west_2_app": [
"10.159.160.0 255.255.248.0",
"10.159.161.0 255.255.248.0"
],
"aws_criticalprd_us_west_2_db": [
"10.159.168.0 255.255.248.0"
]
}
},
"aws_criticalprd_us_west_2_app": [
"10.159.160.0 255.255.248.0",
"10.159.161.0 255.255.248.0"
],
"aws_criticalprd_us_west_2_app_db": {
"aws_criticalprd_us_west_2_app": [
"10.159.160.0 255.255.248.0",
"10.159.161.0 255.255.248.0"
],
"aws_criticalprd_us_west_2_db": [
"10.159.168.0 255.255.248.0"
]
},
"aws_criticalprd_us_west_2_db": [
"10.159.168.0 255.255.248.0"
]
}
这个怎么运作
TTP 使用定义的组运行解析,该组本身将产生以下输出:
[
{
"aws_all_critical_vpcs": {
"group_obj": [
"aws_criticalprd_us_west_2_app_db",
"aws_critical_us_west_2_app_db",
"aws_criticalprd_us_east_1_app_db",
"aws_critical_us_east_1_app_db",
"aws_criticalprd_eu_west_1_app_db",
"aws_critical_eu_west_1_app_db",
"aws_criticalprd_eu_central_1_app_db",
"aws_critical_eu_central_1_app_db"
]
},
"aws_criticalprd_us_west_2_app": {
"subnet": [
"10.159.160.0 255.255.248.0",
"10.159.161.0 255.255.248.0"
]
},
"aws_criticalprd_us_west_2_app_db": {
"group_obj": [
"aws_criticalprd_us_west_2_app",
"aws_criticalprd_us_west_2_db"
]
},
"aws_criticalprd_us_west_2_db": {
"subnet": [
"10.159.168.0 255.255.248.0"
]
}
}
]
使用宏标记中定义的“lookup_objects”函数进一步处理上述结构,该函数递归查找“group_obj”名称,用上述结果中的值替换它们。
如果要运行以上模板,TTP 需要从 github 存储库安装,而不是从 pypi,例如从repo克隆源代码,解压缩并运行“python setup.py install”
推荐阅读
- python - 如何使用文本小部件中插入的某个问题并检查用户是否回答是或否?
- php - 在php中计算数组中具有相同名称的元素
- linux - javax.net.ssl.SSLException:收到致命警报:protocol_version,Java1.8.0_201 使用 TLSv1 而不是默认的 TLSv1.2 进行握手
- python - 如何根据记录中其他 4 个字段的布尔运算符有效地更新数据框中的字段?
- ios - pushViewController 无法执行 segue
- python - PyCharm 改变警告消息的颜色
- java - 无法将月份作为参数发送
- sugarcrm - 如何仅列出登录用户的记录 - SuiteCRM 版本 7.10.4 Sugar 版本 6.5.25 (Build 344)
- .net-4.7.2 - .NET 4.7.2 BadImageFormat 异常随机
- angular6 - 如何在nebular中使用NbWindowService在另一个组件中打开表单