我遇到一个任务问题:
我有来自cisco hw的输出。
IP access list 100
10 permit igmp any any
20 deny any any
IP access list 200
10 permit ip 192.168.1.1/32
20 permit ip 192.168.2.1/32 any
30 permit ip 192.168.3.3/32 any
40 deny any any
任务是制作一个dict,其中访问列表编号为密钥,访问列表规则编号为值。
acl_dict = {'100' : '10', '100' : '20','200': '10', '200': '20', '200': '30', '200': '40'}
我写了一个正则表达式:
rx = re.compile("""
list\s(.*)[\n\r]
\s{4}(\d{1,3}).+$
""",re.MULTILINE|re.VERBOSE)
for match in rx.finditer(text):
print (match.group(1))
print (match.group(2))
但是只显示前两个字符串中的数字(100和10) 我需要以某种方式修改正则表达式以匹配所有数字以使所需的字典。 有人可以帮忙吗?
答案 0 :(得分:2)
可以使用最新的 regex 模块通过单一方法完成此操作:
import regex
text = """
IP access list 100
10 permit igmp any any
20 deny any any
IP access list 200
10 permit ip 192.168.1.1/32
20 permit ip 192.168.2.1/32 any
30 permit ip 192.168.3.3/32 any
40 deny any any
"""
acl_dict = {}
rx = regex.compile("list\s(.+)[\n\r](\s{4}(\d{1,3}).+[\n\r])*", regex.MULTILINE|regex.VERBOSE)
for match in rx.finditer(text):
acl_dict[match.group(1)] = match.captures(3)
print(acl_dict)
输出:
$ python3 match.py
{'200 ': ['10', '20', '30', '40'], '100 ': ['10', '20']}
答案 1 :(得分:1)
您可以先提取完整的块,然后从内部部分获取前导数字(可以捕获)。
使用
r'(?sm)IP access list\s+(\d+)(.*?)(?=^IP access list|\Z)'
请参阅regex demo。
<强>详情:
(?sm)
- 启用DOTALL和MULTILINE模式IP access list
- 文字字符串IP access list
(如果始终位于第一行,则可以加^
)\s+
- 一个或多个空格(\d+)
- 第1组:一个或多个数字(.*?)
- 第2组:任何0 +字符尽可能少到第一个...... (?=^IP access list|\Z)
- IP access list
位于字符串的开头或结尾(\Z
)。import re
input_str = "IP access list 100 \n 10 permit igmp any any \n 20 deny any any \nIP access list 200 \n 10 permit ip 192.168.1.1/32 \n 20 permit ip 192.168.2.1/32 any \n 30 permit ip 192.168.3.3/32 any \n 40 deny any any"
results = {}
for match in re.finditer(r"(?sm)IP access list\s+(\d+)(.*?)(?=^IP access list|\Z)", input_str):
fields = re.findall(r"(?m)^\s*(\d+)", match.group(2))
results[match.group(1)] = fields
print(results) # => {'200': ['10', '20', '30', '40'], '100': ['10', '20']}