Python模式匹配与正则表达式

1. 用正则表达式查找文本模式

 1.1 正则表达式匹配步骤

  1. 用import re导入正则表达式模块
  2. 用re.compile()函数创建一个Regex对象(记得使用原始字符串)
  3. 向Regex对象的search()方法传入想查找的字符串。它返回一个Match对象。
  4. 调用Match对象的group()方法,返回实际匹配文本的字符串。
import re

phone_number = "my phone number is 400-880-9999"

re_phone = re.compile(r'\d{3}-\d{3}-\d{4}')
mo = re_phone.search(phone_number)

print(mo.group())

1.2 用正则表达式匹配更多模式

1.2.1 利用括号分组

假定想要将区号从电话号码中分离。添加括号将在正则表达式中创建“分组”: (\d\d\d)-(\d\d\d-\d\d\d\d)。然后可以使用group()匹配对象方法,从一个分组中获取匹配的文本。

正则表达式字符串中的第一对括号是第1组。第二对括号是第2组。向group()匹配对象方法传入整数 1 或 2,就可以取得匹配文本的不同部分。向group()方法传 入0或不传入参数,将返回整个匹配的文本。

import re

my_phone = 'my phone number is 400-880-9898'

mach_regex = re.compile(r'(\d{3})-(\d{3})-(\d{4})')
mo = mach_regex.search(my_phone)

print(mo.group(1))

如果想要一次就获取所有的分组,请使用groups()方法,注意函数名的复数形式。

import re

my_phone = 'my phone number is 400-880-9898'

mach_regex = re.compile(r'(\d{3})-(\d{3})-(\d{4})')
mo = mach_regex.search(my_phone)

print(mo.groups())
areaCode, mainNumber,secNumber = mo.groups()
print(areaCode)
print(mainNumber)
print(secNumber)

1.2.2 用管道匹配多个分组

  希望匹配许多表达式中的一个时,就可以使用管道。如Tom和jerry同时出现在字符串中,第一次出现的匹配文本,将作为Match对象返回。如下代码

import re
sublien = "Tom and jreey"
sublien1 = "jerry is good Tom"

mo = re.compile(r'Tom|jerry')
mo1 = mo.search(sublien)
print(mo1.group())

mo2 = mo.search(sublien1)
print(mo2.group())

假设你希望匹配'Batman'、'Batmobile'、'Batcopter'和'Batbat'中任意一个。因为所有这 些字符串都以 Bat 开始,所以如果能够只指定一次前缀,就很方便。

import re
sublien = "'Batman is good"

match_test = re.compile(r'Bat(man|mobile|copter|bat)')
mo = match_test.search(sublien)
print(mo.group())
print(mo.group(1))

1.2.3 用问号实现可选匹配

  ?:匹配前面括号字符0次或1次

import re
sublien = "Batman is good"
sublien1 = "Batwoman is good"
match_test = re.compile(r'Bat(wo)?man')
mo = match_test.search(sublien)
mo1 = match_test.search(sublien1)

print(mo.group())
print(mo1.group())

1.2.4 用星号匹配0次或多次

import re
sublien = "Batman is good"
sublien1 = "Batwoman is good"
sublien2 = "Batwowowowowowoman is good"
match_test = re.compile(r'Bat(wo)*man')
mo = match_test.search(sublien)
mo1 = match_test.search(sublien1)
mo2 = match_test.search(sublien2)

print(mo.group())
print(mo1.group())
print(mo2.group())

1.2.5 用+号匹配1次或多次

import re
sublien = "Batman is good"
sublien1 = "Batwoman is good"
sublien2 = "Batwowowowowowoman is good"
match_test = re.compile(r'Bat(wo)+man')
mo1 = match_test.search(sublien1)
mo2 = match_test.search(sublien2)

print(mo1.group())
print(mo2.group())

1.2.6 使用{}匹配特定次数

1.2.7贪心和非贪心匹配

import re

subline = "hahahahaha"
#贪心匹配
subtest = re.compile(r'(ha){3,5}')
mo = subtest.search(subline)
print(mo.group())

#非贪心匹配
subtest1 = re.compile(r'(ha){3,5}?')
mo1 = subtest1.search(subline)
print(mo1.group())

1.2.8 findall()方法

作为 findall()方法的返回结果的总结,请记住下面两点:
  1.如果调用在一个没有分组的正则表达式上,例如\d\d\d-\d\d\d-\d\d\d\d,方法 findall()将返回一个匹配字符串的列表,例如['415-555-9999', '212-555-0000']。
  2.如果调用在一个有分组的正则表达式上,例如(\d\d\d)-(\d\d\d)-(\d\d\d\d),方 法 findall()将返回一个字符串的元组的列表(每个分组对应一个字符串),例如[('415', '555', '1122'), ('212', '555', '0000')]。

import re

subline = "hahahahaha"
#贪心匹配
subtest = re.compile(r'(ha)')
mo = subtest.findall(subline)
print(mo)

1.2.9正则表达式符号

  • ?匹配零次或一次前面的分组。
  • *匹配零次或多次前面的分组。
  • +匹配一次或多次前面的分组。
  • {n}匹配 n 次前面的分组。
  • {n,}匹配 n 次或更多前面的分组。
  • {,m}匹配零次到 m 次前面的分组。
  • {n,m}匹配至少 n 次、至多 m 次前面的分组。
  • {n,m}?或*?或+?对前面的分组进行非贪心匹配。
  • ^spam 意味着字符串必须以 spam 开始。
  • spam$意味着字符串必须以 spam 结束。
  • .匹配所有字符,换行符除外。
  • \d、\w 和\s 分别匹配数字、单词和空格。
  • \D、\W 和\S 分别匹配出数字、单词和空格外的所有字符。
  • [abc]匹配方括号内的任意字符(诸如 a、b 或 c)。
  • [^abc]匹配不在方括号内的任意字符。

1.2.10不区分大小写的匹配

re.IGNORECASE参数

import re

subline = "my name is root,the ROOT is haha"

subline_test = re.compile(r'(root)',re.IGNORECASE)
mo = subline_test.findall(subline)

print(mo)

1.1.11用sub()方法替换字符串

Regex 对象的 sub()方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹配。第二个参数是一个字符串,即正则表达式

import re

subline = "my name is root,the ROOT is haha"

subline_test = re.compile(r'(root)',re.I)

mo = subline_test.sub('master',subline)

print(mo)

通过传入 re.DOTALL 作为 re.compile()的第 二个参数,可以让句点字符匹配所有字符,包括换行字符。

re.VERBOSE表示增加注释

re.IGNORECASE表示忽略大小写

 

posted @ 2023-07-11 17:54  摩天居士-谢烟客  阅读(93)  评论(0编辑  收藏  举报