Python 正则表达式跨多行处理
我正在用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')]
>>>
更新: 因为提问者修改了问题,感谢汤姆指出这一点。