python 正则表达式基础

推荐网站 http://www.runoob.com/python 非常适合python学习。

边看网站边敲代码记下来,如下。

正则表达式

正则表达式用于检查一个字符串是否与某种模式相匹配,re模块使得Python拥有全部的正则表达式的功能. 模式字符串 <---> pattern

re.match(pattern, string, flags):从起始位置匹配一个模式,如果不是起始位置匹配成功的话,match(pattern, string, flags)返回None.如果匹配成功的话,就返回一个匹配的对象.

In [19]:
import re
In [26]:
index = re.match('www', 'www.runoob.com').span()# span()获取匹配对象在string中下标范围的元组.
print(index, type(index))
print(re.match('www', 'www.runoob.com')) #匹配成功,返回匹配的对象
print(re.match('com', 'www.runoob.com')) #匹配失败,返回匹配的None
(0, 3) <class 'tuple'>
<_sre.SRE_Match object; span=(0, 3), match='www'>
None
In [52]:
# .匹配任意字符,除了换行符
# *匹配一个字符0次或者多次
# +匹配一个字符1次或者无限次
# ?匹配一个字符0次或1次
# () 被括起来的表达式作为分组,从表达式左边开始每遇到一个左括号,组编号+1,分组表达式可以作为一个整体,后边接数量词,如(.*){2}
# []字符集,表示对应位置可以是字符集中任意字符,字符集中的字符可以逐个列出,也可以指定范围,如[a-z]或者[abc]或者[^abc] --  表示非abc
# {num}表示匹配前面的字符多少次,或者{num1, num2}多少次到多少次
# 普通字符:匹配自身
# | 或,匹配|左边表达式或者右边表达式中的一个即可
In [53]:
#group(num=0)
line = 'cats are smarter than dogs?'
matchObj = re.match(r'(.*) are (.*?) (.*)', line, re.M|re.I)
if matchObj:
    print('matchObj.group(): ', matchObj.group())
    print('matchObj.group(1): ', matchObj.group(1))
    print('matchObj.group(2): ', matchObj.group(2))
    print('matchObj.group(1: 3): ', matchObj.group(3))
matchObj.group():  cats are smarter than dogs?
matchObj.group(1):  cats
matchObj.group(2):  smarter
matchObj.group(1: 3):  than dogs?
In [59]:
# ^ 上三角号,匹配字符串开头,在多行模式中匹配每一行的开头
In [71]:
string1 = 'cat are cats smart'
pattern1 = '^cats'
pattern2 = 'cats'
print(re.search(pattern1, string1, re.M|re.I))
print(re.search(pattern2, string1, re.M|re.I))
None
<_sre.SRE_Match object; span=(8, 12), match='cats'>
In [72]:
# $ 匹配字符串末尾
In [81]:
a1 = 'we are students '
print(re.search('\s$', a1, re.M|re.I)) # $匹配结尾,然后从结尾开始倒着匹配前面的pattern
print(re.search('\s', a1, re.M|re.I))
<_sre.SRE_Match object; span=(15, 16), match=' '>
<_sre.SRE_Match object; span=(2, 3), match=' '>
In [159]:
url = '\nabc\nabc\t abd as' # 字符串中出现换行,tab,在输出时,都是会真的换行和tab,这个就是它们的原意,在替换时,就是用它们本身匹配就行
urll = r'\nabc\nabc\t abd as' #字符中出现换行,tab,在字符串前有r时,输出会把它们当成字符打印,这个不是它们的原意,替换时,要转意
#print(url)
#print(urll)
print(url.replace('\n', ''))
print(url.replace(' ', ''))
print(url.replace('\t', ''))
print(urll.replace('\\t', ''))
print(urll.replace('\\n', '')) # \\n是对\n进行转意为普通字符
print(urll.replace(r'\n', '')) # 与上一个等价
abcabc	 abd as

abc
abc	abdas

abc
abc abd as
\nabc\nabc abd as
abcabc\t abd as
abcabc\t abd as

re.research(pattern, string, flags):扫描整个字符串并返回第一个成功的匹配

In [92]:
print(re.search('www', 'www.runoob.com').span())
print(re.search('com', 'www.runoob.com').span())
(0, 3)
(11, 14)
In [183]:
#问号匹配,也要转义
In [96]:
print(re.search('\?', 'www.ru?noob.com').span()) 
(6, 7)

re.match和re,research的区别:前者只匹配字符串的开始,如果字符串开始不符合正则表达式,就匹配失败;后者是匹配整个字符串,直到找到一个匹配

检索和替换

re.sub(pattern, repl, string, count=0):替换字符串中的匹配项 pattern:模式串 repl:替换成的字符串 string:原始字符串 count:模式匹配后,替换的最大次数,默认count=0表示替换所有的匹配

In [99]:
phone = '2004-938-3333 #this is a phone number'
#删掉注释,获取电话号码
print(re.sub('#.*$', '', phone))
#移出非数字内容,获取电话号码
print(re.sub('\D', '', phone))
2004-938-3333 
20049383333

re.subn(pattern, repl, string, count=0, flags=0)返回替换次数

In [182]:
print(re.subn(r'g.t', 'have', 'i get a, i got b, i gut c'))
('i have a, i have b, i have c', 3)
In [ ]:
def double_num(matched):
    value = (int)(matched.groups())
    

re.compile(pattern[,flags]):用于编译正则表达式,生成一个正则表达式对象,供match和search使用,编译后速度会快一点. flags参数:可选,表示匹配模式,比如忽略大小写,多行模式,具体参数有: re.I 忽略大小写 re.L 做本地识别匹配,法语等 re.M 多行模式 re.S 含义为.并且包含换行符在内的任意字符 re.U 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B re.X 该标志通过给予更灵活的格式以便将正则表达式书写的更易于理解

In [104]:
pattern = re.compile(r'\d+') #匹配一个或者多个数字的正则表达式对象
m = pattern.match('one12twothree34four') #匹配失败,返回None
print(m)
m = pattern.match('one12twothree34four', 2, 10)
print(m)
m = pattern.match('one12twothree34four', 3, 10) #匹配成功,返回一个match对象
print(m)
None
None
<_sre.SRE_Match object; span=(3, 5), match='12'>

如何获取match对象用matchObj的值,用matchObj.group()

group()用于获取一个或多个分组匹配的字符串,当要获取整个匹配的子串时,直接使用group()或者group(0)

如何多个分组呢?使用()将表达式括起来,使用多个()就形成了多个分组

如何获得多个分组呢? m.group(),若是获取某个分组m.group(i)

In [111]:
m.group() # 与m.group(0)等价
Out[111]:
'12'
In [112]:
m.group(1)
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-112-650107875ff0> in <module>()
----> 1 m.group(1)

IndexError: no such group

In [114]:
 
           
print(m.start()) #获取分组匹配的子串在整个字符串中的起始位置(下标从0开始)
print(m.end())   #获取分组匹配的子串在整个字符串中的结束位置(子串最后一个位置+1)
print(m.span()) # 返回元组(start(group), end(group()))
3
5
(3, 5)

分组例子如下

In [136]:
pattern = re.compile(r'([a-z]+\s){4}')  #怎么好像{i},i>1以后,就将m分成两组,m.group(0)和m.group(1),其余下边就都会报错,并且m.groups()也只会得到仅包含、最后一个匹配子串的元素
# pattern = re.compile(r'([a-z]+\s){1}')
m = pattern.match('hello word hello kitty ')
print(m)
print(m.groups()) #只得到包含一个匹配子串的元组
print(m.group(0))
print(m.span(0))
print(m.group(1))
print(m.span(1))
print(m.group(2)) #出错
<_sre.SRE_Match object; span=(0, 23), match='hello word hello kitty '>
('kitty ',)
hello word hello kitty 
(0, 23)
kitty 
(17, 23)
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-136-a1e38d9d9325> in <module>()
      8 print(m.group(1))
      9 print(m.span(1))
---> 10 print(m.group(2)) #出错

IndexError: no such group

re.split(pattern, string, maxsplit=0,flags)功能是按照能够匹配的子串将字符串分割后返回元素为字符串的列表

#不保留匹配子串的列表

In [156]:
re.split('\d+', 'one1two2three3')
re.split('\d+', '0one1two2three3')
Out[156]:
['', 'one', 'two', 'three', '']

#包含匹配子串的列表

In [157]:
mm = re.split('(\d+)', '0one1two2three3') 
print(mm) #这是列表
['', '0', 'one', '1', 'two', '2', 'three', '3', '']
In [146]:
print(re.split('\d+', '0one1two2three3',1))
print(re.split('\d+', '0one1two2three3',2))
['', 'one1two2three3']
['', 'one', 'two2three3']
In [151]:
re.split('a*', 'hello word') #无法匹配,就不划分,返回列表,元素为字符串
C:\ProgramData\Anaconda3\lib\re.py:212: FutureWarning: split() requires a non-empty pattern match.
  return _compile(pattern, flags).split(string, maxsplit)
Out[151]:
['hello word']

正则表达式对象:re.RegexObject,re.compile()返回正则表达式对象 RegexObject 对象,有match/search/split方法;

正则表达式对象:re.MatchObject()对象,由re.match()返回,有group/start/end/span方法.

re.I/re.L/re.U/re.S/re.M.re.X是正则表达式修饰符flags参数项,可选,flags等于多个值,使用|连接

In [177]:
print(re.split('a', '1A1aweAds12', maxsplit=0, flags=re.I))
['1', '1', 'we', 'ds12']

pattern.findall(string, start, end)在字符串中找到正则表达式匹配的所有子串,并返回一个列表,没找到返回空列表.

re.findall与match/search区别:前者是匹配所有,后者是一次匹配

In [172]:
 
           
pattern = re.compile(r'\d+')
result1 = pattern.findall('asd 12 ewjekjwk 45 dks')
result2 = pattern.findall('asd 12 ewjekjwk 45 dks', 0, 10)
print(result1, result2)
['12', '45'] ['12']

re.finditer(pattern, string, flags)在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回

如何遍历迭代器的值呢?for循环 + match.group()

In [173]:
it = re.finditer(r'\d+', '12mkm3ew2ewe')
for match in it:
    print(match.group())
12
3
2

正则表达式模式

多数子母和数字前面加一个反斜杠会表示不同的含义

标点符号只有被转义才能匹配自身,否则有特殊含义,比如.和?和\

In [160]:
print(re.search(',', 'abc,s'))
<_sre.SRE_Match object; span=(3, 4), match=','>
In [161]:
 
           
print(re.search('.', 'abc,s'))
<_sre.SRE_Match object; span=(0, 1), match='a'>
In [163]:
print(re.search('!', 'abc,s!'))
<_sre.SRE_Match object; span=(5, 6), match='!'>

由于正则表达式通常都包含反斜杠,所以最好使用原始字符串表示它们

即r'\t' 与 '\t'等价.

In [181]:
#匹配电话号码
p = re.compile(r'\d{3}-\d{6}')
print(p.findall('010-26088880'))
['010-260888']

\d 匹配一个数字字符,等价于[0-9]

\D 匹配一个非数字字符,等价于[^0-9]

\s 匹配任何空白字符,包括空格、制表符、换页符等,等价于[\f\n\r\t\v]

\S 匹配任何非空白字符,等价于[^\f\n\r\t\v]

\w 匹配包括下划线的任何单词字符,等价于[A-Za-z0-9_]

\W 匹配任何非单词字符,等价于[^A-Za-z0-9_]

猜你喜欢

转载自blog.csdn.net/qq_23534759/article/details/80487376