【问题描述】
用户输入一段文字,其中包含两个合法的IP地址。编写程序找出其中的IP地址,并输出结果。
输入数据:
服务器1的IP地址是:192.168.3.112,服务器2的IP地址是:192.168.3.122
输出结果:
['192.168.3.112','192.168.3.122']
【题前思考】
根据问题描述,填写表10-1-7。
表10-1-7 问题分析
【解题思路】
IP地址的格式是×××.×××.×××.×××,每个×代表一个阿拉伯数字。解决问题的关键是写出IP地址的正则表达式,然后根据需要选择调用re模块中的match( )、search( )或findall( )等方法,求解问题。
【程序代码】
【代码分析】
①:pattern字符串是提取IP地址使用的正则表达式,前加r表示一个普通字符串,去掉反斜杠的转义机制。(?:…)匹配在括号内的任何正则表达式,但该分组所匹配的子字符串不能在执行匹配后被获取或是之后在模式中被引用,捕获组将在下一节中介绍。“\d{1,3}”匹配1~3个数字,“\.\d{1,3}”匹配一个“.”且后跟1~3个数字。“(?:\.\d{1,3}){3}”表示小括号构成一个组,这个组恰好重复3次,等同于“\.\d{1,3}\.\d{1,3}\.\d{1,3}”;加"?:"构成非捕获组,否则findall( )方法将返回捕获组列表,而不是完整的IP地址。
②:调用re.findall( )方法找到段落中的所有IP地址,匹配过程如图10-1-5所示。
图10-1-5 IP地址匹配样式
③:针对案例提供的输入数据,结果为两个IP地址串构成的列表。
【优化提升】
代码第①行提供的正则表达式,不能验证IP地址的合法性。例如,该正则表达式可以匹配“333.333.333.333”,但这显然不是一个合法的IP地址。因为IP地址为32位,分为4个8位段,用点号分隔,每小段的取值范围是0~255。而333大于255,不合法。使用下面的正则表达式可以提取合法的IP地址。
pattern=r'(?<!\d)(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-'\r'9]|[01]?[0-9][0-9]?)(?!\d)'
注意,本文提出的方案可能不是最优的。
【技术全貌】
Python字符串前加r,如r'\n\n\n\n',表示一个普通字符串“\n\n\n\n”,而不表示换行,去掉反斜杠的转义机制;加u表示后面字符串以unicode格式进行编码,一般用在中文字符串前面,防止中文乱码;加b表示后面字符串是bytes类型,用于网络编程中。表10-1-8列出了正则表达式中特殊符号的作用。
表10-1-8 特殊符号的作用