当前位置:嗨网首页>书籍在线阅读

02-不用正则表达式来查找文本模式

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

7.1 不用正则表达式来查找文本模式

假设你希望在字符串中查找电话号码。你知道模式:3个数字+一个短横线+3个数字+一个短横线+4个数字,如415-555-4242。

假定我们用一个名为 isPhoneNumber() 的函数来检查字符串是否匹配模式,它返回 TrueFalse 。打开一个新的文件编辑器窗口,输入以下代码,然后保存为isPhoneNumber.py:

def isPhoneNumber(text):
  ❶ if len(text) != 12:
        return False
    for i in range(0, 3):
       ❷ if not text[i].isdecimal():
            return False
  ❸ if text[3] != '-':
        return False
    for i in range(4, 7):
       ❹ if not text[i].isdecimal():
            return False
  ❺ if text[7] != '-':
        return False
    for i in range(8, 12):
       ❻ if not text[i].isdecimal():
            return False
  ❼ return True
print('415-555-4242 is a phone number:')
print(isPhoneNumber('415-555-4242'))
print('Moshi moshi is a phone number:')
print(isPhoneNumber('Moshi moshi'))

运行该程序,输出结果像这样:

415-555-4242 is a phone number:
True
Moshi moshi is a phone number:
False

isPhoneNumber() 函数进行了几项检查,看看 text 中的字符串是不是有效的电话号码。如果其中任意一项检查失败,函数就返回 False 。函数首先检查该字符串是否刚好有12个字符❶。然后它检查区号(就是 text 中的前3个字符)是否只包含数字❷。函数剩下的部分检查该字符串是否符合电话号码的模式:号码必须在区号后出现第一个短横线❸,3个数字❹,然后是另一个短横线❺,最后是4个数字❻。如果程序执行通过了所有的检查,它就返回True❼。

用参数 '415-555-4242' 调用 isPhoneNumber() 将返回 True 。用参数 'Moshi moshi' 调用 isPhoneNumber() 将返回 False ,这项测试失败了,因为不是12个字符。

如果想在更长的字符串中寻找电话号码,就必须添加更多代码来寻找电话号码模式。用下面的代码替代isPhoneNumber.py中的最后4个 print() 函数调用:

message = 'Call me at 415-555-1011 tomorrow. 415-555-9999 is my office.'
for i in range(len(message)):
  ❶ chunk = message[i:i+12]
  ❷ if isPhoneNumber(chunk):
         print('Phone number found: ' + chunk)
print('Done')

该程序运行时,输出结果看起来像这样:

Phone number found: 415-555-1011
Phone number found: 415-555-9999
Done

for 循环的每一次迭代中,取自 message 的一段新的12个字符被赋给变量 chunk ❶。例如,在第一次迭代时, i 是0, chunk 被赋值为 message[0:12] (即字符串 'Call me at 4' )。在下一次迭代时, i 是1, chunk 被赋值为 message[1:13] (即字符串 'all me at 41' )。换言之,在 for 循环的每次迭代中, chunk 取以下的值:

  • 'Call me at 4'
  • 'all me at 41'
  • 'll me at 415'
  • 'l me at 415-'
  • ……

chunk 传递给 isPhoneNumber() ,看看它是否符合电话号码的模式❷。如果符合,就输出这段文本。

继续遍历 message ,最终 chunk 中的12个字符会是一个电话号码。该循环遍历了整个字符串,测试了每一段12个字符,输出所有满足 isPhoneNumber()chunk 。当我们遍历完 message ,就输出 Done

虽然在这个例子中 message 中的字符串很短,但它也可能包含上百万个字符,程序运行仍然不需要1秒。使用正则表达式编写查找电话号码的类似程序,运行也不会超过1秒,但用正则表达式编写这类程序会快得多。