我试图匹配来自subprocess
输出的IP和MAC地址,但似乎我有两个问题(我可以看到)。 regx不是很好,因为它缺少一些项目而另一个问题是,由于某种原因,OS X没有为arp -a
命令生成正确的MAC地址输出。
我讨厌regx :(,我确实开始使用socket.inet_aton()
来验证IP地址但迭代每一行并尝试将regx与mac匹配并使用socket.inet_aton(addr)
进行验证并不是特别有用。所以决定在两个方面都使用regx。
我理解为什么不正确的格式化输出没有匹配(MAC)和那个问题我会在其他地方尝试地址,但我无法弄清楚为什么没有匹配正确格式化的输出。我提到过我讨厌过regx吗? :)
更新
我最初没有注意到以下行中的单个数字? (192.168.1.74) at fc:75:16:3:d0:2a on en0 ifscope [ethernet] # Not missing anything but does not match
所以我的问题似乎是OSx没有正确打印MAC。由于某种原因,如果它是0
,它看起来会脱离某个段的第一个数字。因此,我需要在任何单个数字段的前面添加一个0
来解决我的问题(直到我弄清楚为什么它首先这样做。在其他系统上测试不会产生这个单个数字段在mac地址中。
脚本输出
? (192.168.1.74) at fc:75:16:3:d0:2a on en0 ifscope [ethernet] # Not missing anything but does not match
192.168.1.74
? (192.168.1.115) at 28:32:c5:f1:eb:9e on en0 ifscope [ethernet]
192.168.1.115
28:32:c5:f1:eb:9e
? (192.168.1.126) at 0:c:29:30:a1:c9 on en0 ifscope [ethernet] #Notice the misson 0 ?
192.168.1.126
gateway.home (192.168.1.254) at f4:55:9c:62:8a:cc on en0 ifscope [ethernet]
192.168.1.254
f4:55:9c:62:8a:cc
? (192.168.1.255) at ff:ff:ff:ff:ff:ff on en0 ifscope [ethernet]
192.168.1.255
ff:ff:ff:ff:ff:ff
? (192.168.7.1) at 0:50:56:c0:0:8 on vmnet8 ifscope permanent [ethernet] #Notice the misson 0 ?
192.168.7.1
? (192.168.194.1) at 0:50:56:c0:0:1 on vmnet1 ifscope permanent [ethernet] #Notice the misson 0 ?
192.168.194.1
脚本
cmd="arp -a"
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
output, errrors = process.communicate()
for line in output.split("\n"):
print line
for data in line.split(' '):
data = data.translate(None, '()')
mac = re.match("^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$", data)
if mac:
print mac.group()
ip = re.match("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", data)
if ip:
print ip.group()
答案 0 :(得分:1)
MAC地址正则表达式(由@nhahtdh指出)不考虑单个数字(或字母)段,我也使用单个正则表达式(避免循环并减少代码)。 / p>
#!/usr/bin/python
import subprocess
import re
cmd = "arp -a"
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
output, errors = process.communicate()
for line in output.split("\n"):
if line and not line.isspace():
print "line ->", line
regex = re.match("(?i).*?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*?((?:[0-9A-F]{1,2}[:]){5}(?:[0-9A-F]{1,2}))", line)
print "ip ->", regex.group(1)
print "mac ->", re.sub('(^[^:](?=:)|(?<=:)[^:](?=:)|(?<=:)[^:]$)', '0\\1', regex.group(2))
答案 1 :(得分:0)
当前接受的答案过于复杂。无需拆分字符串。您遇到的问题是^
和$
与字符串的开头/结尾而不是行匹配。要使它们与行尾匹配,只需将re.MULTILINE
传递给编译标志。
使用上面的脚本,它就是:
cmd="arp -a"
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
output, errrors = process.communicate()
mac_matcher = re.compile("^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$", re.M)
ip_matcher = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", re.M)
# I'm using search here to just get the first value, but you can iterate instead
mac = mac_matcher.search(output)
ip = ip_matcher.search(output)