Python Regex与子进程输出的关系

Python Regex与子进程输出的关系,python,regex,Python,Regex,我正在尝试从子流程输出匹配IP和MAC地址,但似乎我有两个问题(我可以看到)。regx不是很好,因为它缺少一些项,另一个问题是,由于某些原因,osx没有为arp-a命令生成正确的MAC地址输出 我讨厌regx:(,我开始时确实使用了socket.inet_aton()来验证ip地址,但迭代每一行并尝试将regx与mac匹配,并使用socket进行验证。inet_aton(addr)不是特别有用。因此决定在这两方面都使用regx 我理解为什么不正确的格式化输出不匹配(MAC),我将尝试在其他地方解

我正在尝试从
子流程
输出匹配IP和MAC地址,但似乎我有两个问题(我可以看到)。regx不是很好,因为它缺少一些项,另一个问题是,由于某些原因,osx没有为
arp-a
命令生成正确的MAC地址输出

我讨厌regx:(,我开始时确实使用了
socket.inet_aton()
来验证ip地址,但迭代每一行并尝试将regx与mac匹配,并使用
socket进行验证。inet_aton(addr)
不是特别有用。因此决定在这两方面都使用regx

我理解为什么不正确的格式化输出不匹配(MAC),我将尝试在其他地方解决这个问题,但我无法找出为什么不匹配正确格式化的输出。我是否提到我讨厌regx?:)

更新

我最初没有注意到下一行中的单个数字
?(192.168.1.74)在en0 ifscope[以太网]上的fc:75:16:3:d0:2a处#没有遗漏任何内容,但不匹配
,因此我的问题似乎更多的是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()
脚本

? (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()

MAC地址正则表达式(如@ nHaHTDH所指出的)不考虑一个数字(或字母)段,我也使用了一个单一的正则表达式(以避免循环和减少代码)。

!/usr/bin/python
导入子流程
进口稀土
cmd=“arp-a”
process=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
输出,错误=process.communicate()
对于输出中的行。拆分(“\n”):
if line和not line.isspace():
打印“line->”,第行
regex=re.match((?)*?(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})。*?(((?:[0-9A-F]{1,2}[:]){5(?}:[0-9A-F]{1,2}]),第行)
打印“ip->”,正则表达式组(1)

打印“mac->”,re.sub('(^[^:](?=:)|(?当前接受的答案过于复杂。不需要拆分字符串。您遇到的问题是
^
$
匹配字符串的开始/结束,而不是一行。要使它们匹配行的结束,只需将
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)

您的正则表达式假定为两个十六进制数字。请将
[0-9A-Fa-f]{2}
更改为
[0-9A-Fa-f]{1,2}
,它应该可以工作。是的,我知道它在寻找2位数字,我不知道有哪一个MAC地址只有1位。我没有注意到上面输出的第一行中的MAC有1位数字。从外观上看,OSx一开始就不能正确打印出来。因此,似乎我需要在任何1位数字的findi中添加一个
0
ngs(如果它是段的第一个数字,则看起来它会去掉第一个
0
).arr是的,这是处理regx的一种更好的方法。谢谢你,一旦我解决了如何将缺少的
0
添加到每个单位数段,我将使用上面的regex示例。@iNoob我编辑了答案,用零填充mac地址的单个部分(如果由单字符组成)哈哈,谢谢你,我采取了不同的方法,但你的方法更好。@iNoob我不知道是否更好(你可以通过
:“
来解决MAC地址拆分问题,并处理每个元素)。当然,对于一个讨厌正则表达式的人来说,这更难看了:PI只是讨厌它,因为我的方法从来都不能正确工作。哈哈,再次感谢