如何在正则捕获组中排除特定文本?以Cisco ACL解析为例
问题:在正则层面提取Cisco ACL协议时移除"object-group"前缀
现有Cisco ACL条目
access-list office extended permit tcp host 1.1.1.1 host 2.2.2.2 access-list home extended permit object-group PROTOS4 host 4.4.4.4 host 5.5.5.5
现有Python解析代码
import re acl_general_structure = ( r'access-list\s+(?P<policy_name>[A-Za-z0-9\-\_]+)\s+extended\s+(?P<action>permit|deny)' r'\s' r'(?P<protocol>[a-zA-Z0-9]+|(?:object-group\s[A-Za-z\d]+))' r'\s' r'host\s(?P<source>(?:[0-9]{1,3}\.){3}[0-9]{1,3})' r'\s' r'host\s(?P<destination>(?:[0-9]{1,3}\.){3}[0-9]{1,3})' ) f_in_name="xx.config" f_out_name=f_in_name + ".csv" with open(f_in_name, "r", encoding="utf8") as f: for line in f.readlines(): result=re.match(acl_general_structure,line) if result: print(result.groupdict())
当前输出
{'policy_name': 'office', 'action': 'permit', 'protocol': 'tcp', 'source': '1.1.1.1', 'destination': '2.2.2.2'} {'policy_name': 'home', 'action': 'permit', 'protocol': 'object-group PROTOS4', 'source': '4.4.4.4', 'destination': '5.5.5.5'}
期望输出
{'policy_name': 'office', 'action': 'permit', 'protocol': 'tcp', 'source': '1.1.1.1', 'destination': '2.2.2.2'} {'policy_name': 'home', 'action': 'permit', 'protocol': 'PROTOS4', 'source': '4.4.4.4', 'destination': '5.5.5.5'}
解决方案:在正则层面实现需求
可以直接通过修改正则表达式的protocol捕获组来实现,不需要后续字符串处理。核心思路是拆分两个匹配分支:
- 分支1:匹配普通协议字符串(如
tcp),直接捕获到protocol组 - 分支2:先匹配
object-group(不捕获该前缀),再将后面的组名捕获到同一个protocol组
修改后的正则表达式如下:
import re acl_general_structure = ( r'access-list\s+(?P<policy_name>[A-Za-z0-9\-\_]+)\s+extended\s+(?P<action>permit|deny)' r'\s' r'(?:(?P<protocol>[a-zA-Z0-9]+)|object-group\s(?P<protocol>[A-Za-z\d]+))' r'\s' r'host\s(?P<source>(?:[0-9]{1,3}\.){3}[0-9]{1,3})' r'\s' r'host\s(?P<destination>(?:[0-9]{1,3}\.){3}[0-9]{1,3})' ) f_in_name="xx.config" f_out_name=f_in_name + ".csv" with open(f_in_name, "r", encoding="utf8") as f: for line in f.readlines(): result=re.match(acl_general_structure,line) if result: print(result.groupdict())
关键修改说明
- 使用
(?:...)创建非捕获组包裹两个分支,确保正则整体结构不受影响 - 第一个分支
(?P<protocol>[a-zA-Z0-9]+)直接捕获普通协议名 - 第二个分支
object-group\s(?P<protocol>[A-Za-z\d]+)中,object-group\s仅做匹配不捕获,真正的组名被捕获到protocol组中
修改后运行输出
{'policy_name': 'office', 'action': 'permit', 'protocol': 'tcp', 'source': '1.1.1.1', 'destination': '2.2.2.2'} {'policy_name': 'home', 'action': 'permit', 'protocol': 'PROTOS4', 'source': '4.4.4.4', 'destination': '5.5.5.5'}
完全符合期望输出,无需额外处理字典中的protocol值。
内容的提问来源于stack exchange,提问作者Dione Saturn
相关产品推荐
相关产品推荐

