Python内置的re模块可以使我们很方便的使用正则表达式处理字符串或文本,下面我们用一个小的练习来看一下如何使用re模块的match()/compile()等方法。
问题:如何使用python获取linux的网络配置请况并返回包含以下内容的列表:{$nic1_name:$nic1_ip, $nic2_name:$nic2_ip, ...}?
首先,我们需要通过ifconfig命令来获取当前linux的网络配置信息, 我的机器显示如下信息:
stephenw@devbox1:~$ ifconfig br0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.20.10.6 netmask 255.255.255.240 broadcast 172.20.10.15 inet6 fe80::a00:27ff:fe7b:939b prefixlen 64 scopeid 0x20<link> ether 08:00:27:7b:93:9b txqueuelen 1000 (Ethernet) RX packets 29510 bytes 186705629 (186.7 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 23931 bytes 1879466 (1.8 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ether 08:00:27:7b:93:9b txqueuelen 1000 (Ethernet) RX packets 244340 bytes 253658425 (253.6 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 23944 bytes 1928987 (1.9 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 235 bytes 20665 (20.6 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 235 bytes 20665 (20.6 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 ether 52:54:00:ad:03:27 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
我们可以使用python的subprocess模块来得到ifconfig的输出:
import subprocess output = subprocess.check_output(['ifconfig']).decode()
其次,上面的output其实包含多个网卡(虚拟网卡)的配置信息,两个网卡之间的信息实际是用一个空行(实际是两个连续换行符\n\n)分隔的,因此很容易将各网卡的信息分隔开,这样解析网卡名和IP也更高效。我们用str类型的split()来分割网卡信息:
import subprocess output = subprocess.check_output(['ifconfig']).decode() output = output.split('\n\n')
最后,针对每个网卡的配置信息,我们使用正则表达式'(.*) : flags=.*(\n*).*inet (\d+\.\d+\.\d+\.\d+) .*' 来搜索并获取网卡名和IP地址。正则表达式中的每一对小括号称为一个捕获分组,第一对括号用于捕获网卡名(在字符串" : flags="前所有的部分)。第二对括号是为了处理换行符:在上面的输出中,网卡名和IP地址子处于不同的行,我们知道‘.'表示任一字符,但不包含换行符,所以我们在第二对括号中显示加入'\n'。第三对括号是为了匹配IP地址:在字符串"inet "之后的“."分割的数字组合。
#!/usr/bin/python3
import re import subprocess output = subprocess.check_output(['ifconfig']).decode() output = output.split('\n\n') regex = re.compile('(.*): flags=.*(\n*).*inet (\d+\.\d+\.\d+\.\d+) .*')
nic_ip_list = dict() for nic_info in output: result = regex.match(nic_info) if result:
nic_name = result.group[1]
nic_ip = result.group[3]
nic_ip_list[nic_name] = nic_ip
print(nic_ip_list)
输出结果:
{'br0': '172.20.10.6', 'lo': '127.0.0.1', 'virbr0': '192.168.122.1'}