Python——递归字符串查找

标签 python

我正在尝试解析 cisco 配置防火墙输出。我正在尝试递归查找嵌套的object-group,直到找到每个object-group

的IP

这是一个场景示例:

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——递归字符串查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58861229/

相关文章:

python - 运行命令并像在终端中一样近乎实时地分别获取其标准输出、标准错误

python - python 3.3.1连接mysql数据库密码错误

python - fork:关闭所有打开的套接字

python - Django 的评论框架中的get_comment_permalink 是如何工作的?

Python:并行化任何/所有语句

python - 如何设置导入,以便 Airflow 在任务正常运行时不显示错误

python - 是否可以在Hive中按列表查询?

python - 将 Spark Dataframe 拆分为训练和测试

python - 单击图表时显示的勾选标签?

javascript - 难道Python运行时模型是字典的字典吗?