正则表达式

 

https://www.cnblogs.com/chuxiuhong/p/5885073.html

.字符在正则表达式代表着可以代表任何一个字符(包括它本身)

\,其实如果你编程经验较多的话,你就会发现这是好多地方的“转义符”。

+的作用是将前面一个字符或一个子表达式重复一遍或者多遍。

*跟在其他符号后面表达可以匹配到它0次或多次

[]代表匹配里面的字符中的任意一个

[^]代表除了内部包含的字符以外都能匹配

注意:“+”代表是字符重复一次或多次。但是我们没有细说这个多次到底是多少次。所以它会尽可能“贪婪”地多给我们匹配字符,在这个例子里也就是匹配到最后一个“.”。
我们怎么解决这种问题呢?只要在“+”后面加一个“?”就好了。

 

#正则表达式
key = r"<h1>hello world<h1>"
p1 = r"<h1>.+<h1>"
pattern1 = re.compile(p1)
print pattern1.findall(key)

key = r"lalala<hTml>hello</Html>heiheihei"
p1 = r"<[Hh][Tt][Mm][Ll]>.+?</[Hh][Tt][Mm][Ll]>"
pattern1 = re.compile(p1)
print pattern1.findall(key)

key = r"mat cat hat pat"
p1 = r"[^p]at"#这代表除了p以外都匹配
pattern1 = re.compile(p1)
print pattern1.findall(key)

 

2. python中使用正则表达式的步骤

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

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

eg:
>>> phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
>>> mo = phoneNumRegex.search('My number is 415-555-4242.')
>>> mo.group(1)
'415'
Python 编程快速上手——让繁琐工作自动化
>>> mo.group(2)
'555-4242'
>>> mo.group(0)
'415-555-4242'
>>> mo.group()
'415-555-4242'
如果想要一次就获取所有的分组,请使用 groups()方法,注意函数名的复数形式。
>>> mo.groups()
('415', '555-4242')

3. 用管道匹配多个分组【 | 】

字符|称为“管道”。希望匹配许多表达式中的一个时,就可以使用它。例如, 正则表达式 r'Batman|Tina Fey'将匹配'Batman'或'Tina Fey'。如果 Batman 和 Tina Fey 都出现在被查找的字符串中,第一次出现的匹配文本, 将作为 Match 对象返回。

>>> import re
>>> heroregx=re.compile(r'Batman|Tina Fey')
>>> mo1=heroregx.search('Batman and Tina Fey.')
>>> mo1.group()
'Batman'

(2)Tina在前
>>> mo2 = heroRegex.search('Tina Fey and Batman.')
>>> mo2.group()
'Tina Fey'

利用 findall()方法,可以找到“所有”匹配的地方。

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

>>> batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
>>> mo = batRegex.search('Batmobile lost a wheel')
>>> mo.group()
'Batmobile'
>>> mo.group(1)
'mobile'


方法调用 mo.group()返回了完全匹配的文本'Batmobile',而 mo.group(1)只是返
回第一个括号分组内匹配的文本'mobile'。通过使用管道字符和分组括号,可以指定
几种可选的模式,让正则表达式去匹配。
如果需要匹配真正的管道字符,就用倒斜杠转义,即\|。

4. 用问号实现可选匹配【 ?】

有时候,想匹配的模式是可选的。就是说,不论这段文本在不在,正则表达式 都会认为匹配。字符?表明它前面的分组在这个模式中是可选的。

>>> batRegex = re.compile(r'Bat(wo)?man')
>>> mo1 = batRegex.search('The Adventures of Batman')
>>> mo1.group()
'Batman'
>>> mo2 = batRegex.search('The Adventures of Batwoman')
>>> mo2.group()
'Batwoman'

正则表达式中的(wo)?部分表明,模式 wo 是可选的分组。该正则表达式匹配的文本 中,wo 将出现零次或一次。这就是为什么正则表达式既匹配'Batwoman',又匹配'Batman'。 利用前面电话号码的例子,你可以让正则表达式寻找包含区号或不包含区号的 电话号码。

>>> phoneRegex = re.compile(r'(\d\d\d-)?\d\d\d-\d\d\d\d')
>>> mo1 = phoneRegex.search('My number is 415-555-4242')
>>> mo1.group()
'415-555-4242'
>>> mo2 = phoneRegex.search('My number is 555-4242')
>>> mo2.group()
'555-4242'

你可以认为?是在说,“匹配这个问号之前的分组零次或一次”。
如果需要匹配真正的问号字符,就使用转义字符\?。

5. 用星号匹配0次或多次【 * 】

*(称为星号)意味着“匹配零次或多次”,即星号之前的分组,可以在文本中出 Python 编程快速上手——让繁琐工作自动化 现任意次。它可以完全不存在,或一次又一次地重复。

>>> batRegex = re.compile(r'Bat(wo)*man')
>>> mo1 = batRegex.search('The Adventures of Batman')
>>> mo1.group()
'Batman'
>>> mo2 = batRegex.search('The Adventures of Batwoman')
>>> mo2.group()
'Batwoman'
>>> mo3 = batRegex.search('The Adventures of Batwowowowoman')
>>> mo3.group()
'Batwowowowoman'


对于'Batman',正则表达式的(wo)*部分匹配 wo 的零个实例。对于'Batwoman',
(wo)*匹配 wo 的一个实例。对于'Batwowowowoman',(wo)*匹配 wo 的 4 个实例。
如果需要匹配真正的星号字符,就在正则表达式的星号字符前加上倒斜杠,即\*。

6. 用加号匹配1次或多次【()】

*意味着“匹配零次或多次”,+(加号)则意味着“匹配一次或多次”。星号不要求 分组出现在匹配的字符串中,但加号不同,加号前面的分组必须“至少出现一次”。这不 是可选的。

>>> batRegex = re.compile(r'Bat(wo)+man')
>>> mo1 = batRegex.search('The Adventures of Batwoman')
>>> mo1.group()
'Batwoman'
>>> mo2 = batRegex.search('The Adventures of Batwowowowoman')
>>> mo2.group()
'Batwowowowoman'
>>> mo3 = batRegex.search('The Adventures of Batman')
>>> mo3 == None
True


正则表达式 Bat(wo)+man 不会匹配字符串'The Adventures of Batman',因为加号
要求 wo 至少出现一次。
如果需要匹配真正的加号字符,在加号前面加上倒斜杠实现转义:\+。

7. 用花括号匹配特定次数【 {} 】

如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括 号包围的数字。例如,正则表达式(Ha){3}将匹配字符串'HaHaHa',但不会匹配'HaHa', 因为后者只重复了(Ha)分组两次。

除了一个数字,还可以指定一个范围,即在花括号中写下一个最小值、一个逗号和 一个最大值。例如,正则表达式(Ha){3,5}将匹配'HaHaHa'、'HaHaHaHa'和'HaHaHaHaHa'。 也可以不写花括号中的第一个或第二个数字,不限定最小值或最大值。

(Ha){3,}将匹配 3 次或更多次实例,(Ha){,5}将匹配 0 到 5 次实例。花括号让正则表 达式更简短。

这两个正则表达式也匹配同样的模式:
(Ha){3,5}
((Ha)(Ha)(Ha))|((Ha)(Ha)(Ha)(Ha))|((Ha)(Ha)(Ha)(Ha)(Ha))


>>> haRegex = re.compile(r'(Ha){3}')
>>> mo1 = haRegex.search('HaHaHa')
>>> mo1.group()
'HaHaHa'
>>> mo2 = haRegex.search('Ha')
>>> mo2 == None
True

这里,(Ha){3}匹配'HaHaHa',但不匹配'Ha'。因为它不匹配'Ha',所以 search()
返回 None。

8.贪心和非贪心匹配 【 {} 】

在字符串'HaHaHaHaHa'中,因为(Ha){3,5}可以匹配 3 个、4 个或 5 个实例,你可能 会想,为什么在前面花括号的例子中,Match 对象的 group()调用会返回'HaHaHaHaHa', 而不是更短的可能结果。毕竟,'HaHaHa'和'HaHaHaHa'也能够有效地匹配正则表达 式(Ha){3,5}。 Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽 可能匹配最长的字符串。

如果要"非贪心"匹配最短的字符时,即在 结束的花括号后跟着一个问号。

>>> greedyHaRegex = re.compile(r'(Ha){3,5}')
>>> mo1 = greedyHaRegex.search('HaHaHaHaHa')
>>> mo1.group()
'HaHaHaHaHa'
>>> nongreedyHaRegex = re.compile(r'(Ha){3,5}?')
>>> mo2 = nongreedyHaRegex.search('HaHaHaHaHa')
>>> mo2.group()
'HaHaHa'



一般用贪婪的取出:{.*?}

请注意,问号在正则表达式中可能有两种含义:声明非贪心匹配或表示可选的 分组。这两种含义是完全无关的。

9. findall()方法

除了search方法外,Regex对象也有一个findall()方法。search()将返回一个Match 对象,包含被查找字符串中的“第一次”匹配的文本,而 findall()方法将返回一组 字符串,包含被查找字符串中的所有匹配。为了看看 search()返回的 Match 对象只 包含第一次出现的匹配文本。

>>> phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
>>> mo = phoneNumRegex.search('Cell: 415-555-9999 Work: 212-555-0000')
>>> mo.group()
'415-555-9999'

另一方面,findall()不是返回一个 Match 对象,而是返回一个字符串列表,只要
在正则表达式中没有分组。列表中的每个字符串都是一段被查找的文本,它匹配该
正则表达式。


>>> phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') # has no groups
>>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
['415-555-9999', '212-555-0000']


如果在正则表达式中有分组,那么 findall 将返回元组的列表。每个元组表示一个找
到的匹配,其中的项就是正则表达式中每个分组的匹配字符串。

>>> phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)') # has groups
>>> phoneNumRegex.findall('Cell: 415-555-9999 Work: 212-555-0000')
[('415', '555', '1122'), ('212', '555', '0000')]

作为 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')]。

 

10.建立自己的字符分类

有时候你想匹配一组字符,但缩写的字符分类(\d、\w、\s 等)太宽泛。你可 以用方括号定义自己的字符分类。例如,字符分类[aeiouAEIOU]将匹配所有元音字 符,不论大小写。

>>> vowelRegex = re.compile(r'[aeiouAEIOU]')
>>> vowelRegex.findall('RoboCop eats baby food. BABY FOOD.')
['o', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'O', 'O']


也可以使用短横表示字母或数字的范围。例如,字符分类[a-zA-Z0-9]将匹配所
有小写字母、大写字母和数字。
请注意,在方括号内,普通的正则表达式符号不会被解释。这意味着,你不需
要前面加上倒斜杠转义.、*、?或()字符。例如,字符分类将匹配数字 0 到 5 和一个
句点。你不需要将它写成[0-5\.]。
通过在字符分类的左方括号后加上一个插入字符(^),就可以得到“非字符类”。
非字符类将匹配不在这个字符类中的所有字符。

>>> consonantRegex = re.compile(r'[^aeiouAEIOU]')
>>> consonantRegex.findall('RoboCop eats baby food. BABY FOOD.')
['R', 'b', 'c', 'p', ' ', 't', 's', ' ', 'b', 'b', 'y', ' ', 'f', 'd', '.', '
', 'B', 'B', 'Y', ' ', 'F', 'D', '.']

11.插入字符和美元字符

可以在正则表达式的开始处使用插入符号(^),表明匹配必须发生在被查找文 本开始处。类似地,可以再正则表达式的末尾加上美元符号($),表示该字符串必 须以这个正则表达式的模式结束。可以同时使用^和$,表明整个字符串必须匹配该 模式.

例如,正则表达式 r'^Hello'匹配以'Hello'开始的字符串。
>>> beginsWithHello = re.compile(r'^Hello')
>>> beginsWithHello.search('Hello world!')
<_sre.SRE_Match object; span=(0, 5), match='Hello'>
>>> beginsWithHello.search('He said hello.') == None
True

正则表达式 r'\d$'匹配以数字 0 到 9 结束的字符串
>>> endsWithNumber = re.compile(r'\d$')
>>> endsWithNumber.search('Your number is 42')
<_sre.SRE_Match object; span=(16, 17), match='2'>
>>> endsWithNumber.search('Your number is forty two.') == None
True

正则表达式 r'^\d+$'匹配从开始到结束都是数字的字符串
>>> wholeStringIsNum = re.compile(r'^\d+$')
>>> wholeStringIsNum.search('1234567890')
<_sre.SRE_Match object; span=(0, 10), match='1234567890'>
>>> wholeStringIsNum.search('12345xyz67890') == None
True
>>> wholeStringIsNum.search('12 34567890') == None
True

12.通配字符

在正则表达式中,.(句点)字符称为“通配符”。它匹配除了换行之外的所有 字符。

>>> atRegex = re.compile(r'.at')
>>> atRegex.findall('The cat in the hat sat on the flat mat.')
['cat', 'hat', 'sat', 'lat', 'mat']

要记住,句点字符只匹配一个字符,这就是为什么在前面的例子中,要匹配真正的句点,就是用倒斜杠转义:\.。

 

13.用点-星匹配所有字符

有时候想要匹配所有字符串。例如,假定想要匹配字符串'First Name:',接下来 是任意文本,接下来是'Last Name:',然后又是任意文本。可以用点-星(.*)表示“任 意文本”。回忆一下,句点字符表示“除换行外所有单个字符”,星号字符表示“前 面字符出现零次或多次”。

>>> nameRegex = re.compile(r'First Name: (.*) Last Name: (.*)')
>>> mo = nameRegex.search('First Name: Al Last Name: Sweigart')
>>> mo.group(1)
'Al'
>>> mo.group(2)
'Sweigart'

点-星使用“贪心”模式:它总是匹配尽可能多的文本。要用“非贪心”模式匹配 所有文本,就使用点-星和问号。像和大括号一起使用时那样,问号告诉 Python 用非贪 心模式匹配。

>>> nongreedyRegex = re.compile(r'<.*?>')
>>> mo = nongreedyRegex.search('<To serve man> for dinner.>')
>>> mo.group()
'<To serve man>'
>>> greedyRegex = re.compile(r'<.*>')
>>> mo = greedyRegex.search('<To serve man> for dinner.>')
>>> mo.group()
'<To serve man> for dinner.>'

两个正则表达式都可以翻译成“匹配一个左尖括号,接下来是任意字符,接下 来是一个右尖括号”。但是字符串' for dinner.>'对右肩括号有两种可能的 匹配。在非贪心的正则表达式中,Python 匹配最短可能的字符串:''。 在贪心版本中,Python 匹配最长可能的字符串:' for dinner.>'。

 

14.用句点字符匹配换行

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

>>> noNewlineRegex = re.compile('.*')
>>> noNewlineRegex.search('Serve the public trust.\nProtect the innocent.
\nUphold the law.').group()
'Serve the public trust.'
>>> newlineRegex = re.compile('.*', re.DOTALL)
>>> newlineRegex.search('Serve the public trust.\nProtect the innocent.
Python 编程快速上手——让繁琐工作自动化
\nUphold the law.').group()
'Serve the public trust.\nProtect the innocent.\nUphold the law.'


正则表达式 noNewlineRegex 在创建时没有向 re.compile()传入 re.DOTALL,它
将匹配所有字符,直到第一个换行字符。但是,newlineRegex 在创建时向 re.compile()传
入了 re.DOTALL,它将匹配所有字符。这就是为什么 newlineRegex.search()调用匹配完
整的字符串,包括其中的换行字符。

15.正则表达式符号复习

 ?匹配零次或一次前面的分组。
 *匹配零次或多次前面的分组。
 +匹配一次或多次前面的分组。
 {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]匹配不在方括号内的任意字符。

16.不区分大小写的匹配

但是,有时候你只关心匹配字母,不关心它们是大写或小写。要让正则表达式 不区分大小写,可以向 re.compile()传入 re.IGNORECASE 或 re.I,作为第二个参数。

>>> robocop = re.compile(r'robocop', re.I)
>>> robocop.search('RoboCop is part man, part machine, all cop.').group()
'RoboCop'
>>> robocop.search('ROBOCOP protects the innocent.').group()
'ROBOCOP'
>>> robocop.search('Al, why does your programming book talk about robocop so much?').group()
'robocop'

17.用 sub()方法替换字符串

正则表达式不仅能找到文本模式,而且能够用新的文本替换掉这些模式。Regex 对象的 sub()方法需要传入两个参数。第一个参数是一个字符串,用于取代发现的匹 配。第二个参数是一个字符串,即正则表达式。sub()方法返回替换完成后的字符串。

>>> namesRegex = re.compile(r'Agent \w+')
>>> namesRegex.sub('CENSORED', 'Agent Alice gave the secret documents to Agent Bob.')
'CENSORED gave the secret documents to CENSORED.'

【正则分步走】

1.  正则的语法

(1)match
re.match(pattern, string, flags=0) pattern是匹配的正则表达式,string是要匹配的字符串,
#     flags是标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等。

(2) findall
rr=re.compile(pattern) pattern是匹配的正则表达式
rr.findall(string) string是要匹配的字符串

2.Pattern的用法

 举例:

import re

(1)match
line="Hello World Wide Web"
pattern=re.compile(r'([a-z]+)([a-z]+)',re.I)
print(pattern.match(line).group()) #输出“Hello”

(2)findall
tt="Tina is a good girl,she is cool and clever,and so on "
rr=re.compile(r'\w*oo\w*') #\w匹配一个字母或数字,*匹配0次1次或多次。即多次匹配“字符|数字oo字符|数字”的单词
print(rr.findall(tt)) #输出['good', 'cool']

3.flags的用法

flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

re.I 忽略大小写
re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
re.M 多行模式
re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
re.X 为了增加可读性,忽略空格和 # 后面的注释

举例:

import re

line="Hello World Wide Web"
pattern=re.compile(r'([a-z]+)([a-z]+)',re.I)
print(pattern.match(line).group()) #输出“Hello”

提取list中的值:

aa=["江西省上饶市xxxxx19号","上海市徐浩区今晚哦且哦"]
result=[]
for i in aa:
    rr = re.compile(r'\w*上饶市\w*')
    aa1=rr.findall(i)
    result.append(aa1)
print(result)

data_list = ['cat_1', 'dog_1', 'dog_2', 'cat_2', 'dog_3', 'cat_3']  # 原列表中既有dog也有cat, 并且无规律
new_data_list = []  # 保存筛选出来dog的列表
for data in data_list:  # 遍历列表
    if  re.match('dog.*', data) != None:  # 如果正则匹配出的数据不为None, 就将此数据添加到新列表中
        new_data_list.append(data)
print(new_data_list)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值