Python 正则表达式跨多行处理

5 投票
2 回答
24421 浏览
提问于 2025-04-15 16:49

我正在用Python和pexpect从一些思科设备上收集信息,之前用正则表达式提取一些小数据时效果很好。但现在我遇到了一些困难。有些交换机是堆叠在一起的,我在脚本中识别了这一点,并使用了一个单独的程序来解析这些数据。如果交换机是堆叠的,你会看到以下内容(从“sho ver”输出中提取)

Top Assembly Part Number        : 800-25858-06
Top Assembly Revision Number    : A0
Version ID                      : V08
CLEI Code Number                : COMDE10BRA
Hardware Board Revision Number  : 0x01


Switch   Ports  Model              SW Version              SW Image
------   -----  -----              ----------              ----------
*    1   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M  
     2   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     3   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     4   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M


Switch 02 
---------
Switch Uptime                   : 11 weeks, 2 days, 16 hours, 27 minutes
Base ethernet MAC Address       : 00:26:52:96:2A:80
Motherboard assembly number     : 73-9675-15

当我遇到这种情况时,我需要从这4行表格中提取每个交换机的编号和型号(“sw”可以忽略,但交换机的数量可能在1到9之间)。我在处理多行数据时遇到了麻烦,其他部分我都能搞定。有没有什么建议呢?

抱歉,我的正则表达式一开始只是看最后一组“-”直到某个地方,然后我就不知道该怎么继续了!
-{10]\s-{10}(.+)Switch

型号会变化,交换机的数量也会变化,我需要捕捉到这个例子中的4行数据:

*    1   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M  
     2   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     3   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     4   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M

但每个交换机可能是不同的型号,数量在1到9之间。对于这个例子,我希望能得到:

*,1,WS-C3750-48P
,2,WS-C3750-48P
,3,WS-C3750-48P
,4,WS-C3750-48P  

(星号表示主交换机)
但获取这些行会让我走上正确的轨道

2 个回答

17

如果你想让 . 能匹配任何字符,包括换行符,你需要在编译正则表达式时加上 re.DOTALL 这个选项(记住,如果你有多个选项,要用 | 这个位或运算符把它们组合起来)。

不过在这种情况下,我不太确定你真的需要这样做——为什么不试试像下面这样的写法呢:

re.findall(r'(\d+)\s+\d+\s+(WS-\S+)')

假设你识别“模型”的方式是它以 WS- 开头?在这里,findall 的一个结果和下一个结果之间有换行符并不是问题。你能具体解释一下你是怎么识别“模型”的,以及为什么“多行”会成为一个问题吗?也许你想用 re.MULTILINE^ 在每一行的开头都能匹配,这样可以根据行的开头来抓取你的数据……?

8
x="""Top Assembly Part Number        : 800-25858-06
Top Assembly Revision Number    : A0
Version ID                      : V08
CLEI Code Number                : COMDE10BRA
Hardware Board Revision Number  : 0x01


Switch   Ports  Model              SW Version              SW Image
------   -----  -----              ----------              ----------
*    1   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     2   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     3   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M
     4   52     WS-C3750-48P       12.2(35)SE5             C3750-IPBASE-M


Switch 02
---------
Switch Uptime                   : 11 weeks, 2 days, 16 hours, 27 minutes
Base ethernet MAC Address       : 00:26:52:96:2A:80
Motherboard assembly number     : 73-9675-15"""

>>> import re
>>> re.findall("^\*?\s*(\d)\s*\d+\s*([A-Z\d-]+)",x,re.MULTILINE)
[('1', 'WS-C3750-48P'), ('2', 'WS-C3750-48P'), ('3', 'WS-C3750-48P'), ('4', 'WS-C3750-48P')]
>>> re.findall("^(\*?)\s+(\d)\s+\d+\s+([A-Z\d-]+)",x,re.MULTILINE)
[('*', '1', 'WS-C3750-48P'), ('', '2', 'WS-C3750-48P'), ('', '3', 'WS-C3750-48P'), ('', '4', 'WS-C3750-48P')]
>>>

更新: 因为提问者修改了问题,感谢汤姆指出这一点。

撰写回答