首页 > 解决方案 > 如何使用 Python grep 获取 Shorewall 规则文件中的 IP 地址

问题描述

如果我使用 python 创建一个包含要删除的 IP 列表的文件,然后将该文件作为正则表达式规则列表提供给 grep,我可以获得我想要的结果,但不能单独使用 python。

该脚本从 Microsoft 下载 Office365 规则更改的 JSON 源。

然后它只对“删除”更改起作用。

我试过使用 re 和一个简单的字符串比较,都没有产生任何结果或错误。

        ips = changes['ips'] if 'ips' in changes else []
        ip4s = [ip for ip in ips if '.' in ip]

        for ip in ip4s:
            ip_rule = 'net:' + ip
            with open('/etc/shorewall/rules', 'r') as rules_file:
                with open('/tmp/rules', 'w') as tmp_rules_file:
                    for line in rules_file:
                        if not ip_rule in line:
                            tmp_rules_file.write(line)

实际的脚本有 3 个部分用于正则表达式 URL、域和 IP。

前两个工作,但不是 IP 部分。它不会出现任何错误或任何更改。

应该发生的是它创建了一个临时文件,其中不包含应该删除的岸墙规则。

然后当我 vimdiff 旧规则文件和临时文件时,我可以看到需要删除的内容。

实际结果是两个文件完全相同。

在 python 之外的进一步测试表明应该删除 211 行。

我是 python 新手,所以假设我被某些东西绊倒了,只是看不到它。

标签: python

解决方案


让我们用一个带有列表的小例子来试试这个,而不是使用文件。从长远来看,您可以做for line in filefor line in list可以制作一个可以将任何可迭代对象发送到其中的函数。这意味着您可以编写单元测试,显示最小的示例以获得帮助。

所以,让我们有我们的ips

ip4s=["1.1.1.1", "2.2.2.2"]

并输入和输出“文件”:

rules_file = ['net:1.1.1.1', 'net:3.3.3.3']
tmp_rules_file = []

(例如 - 假设您可以使用您的正则表达式以您需要的方式获取格式)

对。因此,当我们执行循环时:

for ip in ip4s:
  ip_rule = 'net:' + ip
  for line in rules_file:
    if not ip_rule in line:
        tmp_rules_file.append(line)

因此,对于每一ip4s行,我们一次查看旧规则文件中的每一行。没有的每一行都"1.1.1.1"被写入...

在此示例中,1.1.1.1确实匹配第一个 IP,因此不写入tmp_rules_file. 但是,3.3.3.3不匹配,因此被写入tmp_rules_file.

下一个 IP 是2.2.2.2- 两行都不匹配,因此当您(再次)回顾整个文件时,规则文件的两行都被放入临时文件中,最终得到:

>>> tmp_rules_file
['net:3.3.3.3', 'net:1.1.1.1', 'net:3.3.3.3']

这表明出了什么问题。

要在一个列表中查找不在另一个列表中的内容,您可以使用列表推导:

[ip for ip in ip4s if 'net:'+ip not in rules_file]

这只是['2.2.2.2']在这种情况下给出。

对于较大的数据,您可能需要使用集合并尝试集合差异操作。

您的问题的主要部分是针对文件的每一行检查一件事 - 如果它匹配一个,它将与其他不匹配,因此被写回。


推荐阅读