正则表达式(Python)——匹配MAC地址

Regular expression (Python) - match MAC address

我有这段文字(来自 ipconfig /all)

Ethernet adapter Local Area Connection:

   Connection-specific DNS Suffix  . :    
   Description . . . . . . . . . . . : Atheros AR8151 PCI-E Gigabit Ethernet    Controller (NDIS 6.20)   
   Physical Address. . . . . . . . . : 50-E5-49-CE-FC-EF   
   DHCP Enabled. . . . . . . . . . . : Yes   
   Autoconfiguration Enabled . . . . : Yes    
   Link-local IPv6 Address . . . . . : fe80::5cba:e9f2:a99f:4499%11(Preferred)    
   IPv4 Address. . . . . . . . . . . : 10.0.0.1(Preferred)    
   Subnet Mask . . . . . . . . . . . : 255.255.255.0   
   Lease Obtained. . . . . . . . . . : ™ 06 €…‚…‘ˆ 2016 20:35:49   
   Lease Expires . . . . . . . . . . : ‰…™‰™‰ 09 €…‚…‘ˆ 2016 21:05:49   
   Default Gateway . . . . . . . . . : 10.0.0.138   
   DHCP Server . . . . . . . . . . . : 10.0.0.138   
   DHCPv6 IAID . . . . . . . . . . . : 240182601   
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-19-7A-1F-FC-50-E5-49-CE-FC-EF   
   DNS Servers . . . . . . . . . . . : 10.0.0.138   
   NetBIOS over Tcpip. . . . . . . . : Enabled    

Ethernet adapter Local Area Connection* 11:   

   Description . . . . . . . . . . . : Juniper Networks Virtual Adapter    
   Physical Address. . . . . . . . . : 02-05-85-7F-EB-80     
   DHCP Enabled. . . . . . . . . . . : No    
   Autoconfiguration Enabled . . . . : Yes    
   Link-local IPv6 Address . . . . . : fe80::8dfb:6d42:97e1:2dc7%19(Preferred)     
   IPv4 Address. . . . . . . . . . . : 172.16.2.7(Preferred)      
   Subnet Mask . . . . . . . . . . . : 255.255.255.255     
   Default Gateway . . . . . . . . . :       
   DHCPv6 IAID . . . . . . . . . . . : 436340101     
   DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-19-7A-1F-FC-50-E5-49-CE-FC-EF    
   DNS Servers . . . . . . . . . . . : 172.16.0.6     
                                       172.16.0.91     
   NetBIOS over Tcpip. . . . . . . . : Enabled     

我只想处理物理地址 (MAC)

从这里开始是 2:
50-E5-49-CE-FC-EF02-05-85-7F-EB-80

这 (link) ([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2}) 将不起作用,因为
这也会 00-01-00-01-19-7A-1F-FC-50-E5-49-CE-FC-EF
所以我已将其修复为 ([^-])([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})([^-]) (强制不要-开始和结束)
但是现在我在开始的时候得到了空白,最后我得到了 /n.
这是 link: https://regex101.com/r/kJ7mC0/1

我需要一个 elegant regex 来解决它。

你在两边得到非 - 符号,因为否定字符 class [^-] 匹配并消耗字符。为避免在匹配值中获取这些字符,您可以使用环视:

p = re.compile(r'(?<!-)(?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2}(?!-)', re.IGNORECASE)
                 ^^^^^^                                  ^^^^

(?<!-) 负向后视确保在您需要提取的值之前没有 -,而 (?!-) 是一个负向后视,如果存在 - 在这个值之后。

如果不需要 : 分隔符,请将 [:-] 替换为 -。与 re.findall.

一起使用

另外,所有(...)都应该转为(?:...)非捕获组,以免"spoil"匹配结果。

Python demo

另一种方法可以是正则表达式,其中包含 1 个捕获组,用于捕获我们需要的内容,并匹配我们不需要的内容:

p = re.compile(r'(?:^|[^-])((?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2})(?:$|[^-])', re.IGNORECASE)

它看起来不那么优雅,但与 (?:^|[^-]) 的工作方式相同 re.findall 非捕获组不包含在 re.findall 结果中,并且匹配字符串的开头或符号除了 -(?:$|[^-]) 匹配字符串结尾或 - 以外的符号。

此外,要缩短模式,您可以将字符 class 中的 a-fA-F 替换为 a-f,并使用 re.IGNORECASEre.I旗帜.