正则,re模块

Posted 小杜要加油

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则,re模块相关的知识,希望对你有一定的参考价值。

一、正则表达式(精准匹配)

  匹配字符串内容的一种规则

二、字符组

  在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示
  常见字符组格式如下:[0123456789],[0-9],[a-z],[A-Z],必须由从小到大,不可逆序。

三、主要元字符

[^s]除了s不能匹配
a|b == [ab]
表示匹配任意字符:[\\w\\W],[\\d\\D],[\\s\\S]
 熟记(\\w , \\d ,^ ,$ ,a|b , () ,[...] ,[^...]

\\d+\\.?\\/\\d*
式子前面必须有,后面可无

转义符\\
元字符 匹配内容 元字符 匹配内容
. 匹配除换行符以外的任意字符 $ 匹配字符串的结尾
\\w 匹配字母或数字或下划线(word) \\W 匹配非字母或数字或下划线
\\s 匹配任意的空白符(space) \\S 匹配非空白符
\\d 匹配数字(digit) \\D 匹配非数字
\\n 匹配一个换行符(next) a|b 匹配字符a或字符b
\\t 匹配一个制表符(table) () 匹配括号内的表达式,也表示一个组
\\b 匹配一个单词的结尾 [...] 匹配字符串中的字符
^ 匹配字符串的开始 [^...] 匹配除了字符串中字符的所有字符

#
. ^ $ 例子 import re obj1 = re.findall(\'海.\',\'海燕海南海西\') print(obj1) # [\'海燕\', \'海南\', \'海西\'] 匹配所有带‘海’的字符 obj1 = re.findall(\'^海.\',\'海燕海南海西\') print(obj1) # [\'海燕\'] 只从开头匹配带海的字符 obj1 = re.findall(\'海.$\',\'海燕海南海西\') print(obj1) # [\'海西\'] 只匹配结尾带海的字符

量词:

由于贪婪匹配的原因,在满足匹配条件的情况下,默认按贪婪匹配,即尽可能多的匹配字符串,若在量词后面加上?,即可

将贪婪匹配更改为非贪婪匹配,即匹配尽量短的字符串,常见量词及其主要用法如下:

贪婪模式:

量词 用法说明 量词 用法说明
* 重复零次或更多次 {n} 重复n次
+ 重复一次或更多次 {n,} 重复n
? 重复零次或一次 {n,m} 重复n到m次

 

 

 

 

 

import re
func1
= re.findall(\'李.?\',\'李杰和李立秋和李梵高先生\') print(func1) # [\'李杰\', \'李立\', \'李梵\'] ?表示匹配0或者1次,即匹配李后面任意字符1次
func2 = re.findall(\'李.*\',\'李杰和李立秋和李梵高先生\') print(func2) # [\'李杰和李立秋和李梵高先生\'] *表示匹配0次或多次
func3 = re.findall(\'李.+\',\'李杰和李立秋和李梵高先生\') print(func3) # [\'李杰和李立秋和李梵高先生\'] + 表示匹配1次或多次
func4 = re.findall(\'李.{1,2}\',\'李杰和李立秋和李梵高先生\') print(func4) # [\'李杰和\', \'李立秋\', \'李梵高\'] {1,2} 表示匹配1到2次,即匹配李后面任意字符2次

非贪婪模式:

非贪婪模数 用法说明
*? 重复0次或更多次,但尽可能少重复
+?
重复1次或更多次,但尽可能少重复
??
重复0次或1次,但尽可能少重复
{n,}?
重复n次以上,但尽可能少重复
{n,m}?
重复n到m次,但尽可能少重复

 

 

 

 

 

 

 

.*> 遇到>即停止匹配

func4 = re.findall(\'李.{1,2}?\',\'李杰和李立秋和李梵高先生\')
print(func4)  # [\'李杰\', \'李立\', \'李梵\'] ,重复1次

func5 = re.findall(\'李.??\',\'李杰和李立秋和李梵高先生\') print(func5) # [\'李\', \'李\', \'李\'] ,重复0次
func6= re.findall(\'李.+?\',\'李杰和李立秋和李梵高先生\') print(func6) # [\'李杰\', \'李立\', \'李梵\'] ,重复1次
func7= re.findall(\'李.*?\',\'李杰和李立秋和李梵高先生\') print(func7) # [\'李\', \'李\', \'李\'] ,重复0次

字符集 [ ] [^]

func8 = re.findall(\'李.[杰立秋梵高先生]*\',\'李杰和李立秋和李梵高先生\')
print(func8)   # [\'李杰\', \'李立秋\', \'李梵高先生\']  表示匹配"李"字后面[杰立秋梵高先生]的字符任意次

func9 = re.findall(\'李.[^和]*\',\'李杰和李立秋和李梵高先生\') print(func9) # [\'李杰\', \'李立秋\', \'李梵高先生\'] 表示匹配李后面不是和的任意字符
func10 = re.findall(\'[\\d]\',\'1220shi6\') print(func10) # func10 = re.findall(\'[\\d]*\',\'1220shi6\') print(func10) # [\'1\', \'2\', \'2\', \'0\', \'6\'] 表示匹配任意一个数字
func11 = re.findall(\'[\\d]*\',\'1220shi6\') print(func11) # [\'1220\', \'\', \'\', \'\', \'6\', \'\']
func12 = re.findall(\'[\\d]+\',\'1220shi6\') print(func12) # [\'1220\', \'6\'] 表示匹配任意个数字

分组()与或|

  身份证号码是由15位或者18位的字符组成,如果是15位,首位不能是0,其他位数均为数字,如果是18位,则最后一位可能  是数字或者X,用正则表达式匹配的两种方式如下:

正则表达式 结果说明
^[1-9]\\d{14}(\\d{2}[0-9x])?$
()表示分组,将\\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次
^([1-9]\\d{16}[0-9x]|[1-9]\\d{14})$
表示先匹配[1-9]\\d{16}[0-9x]如果没有匹配上就匹配[1-9]\\d{14}
import re
phone_number = input(\'please input your phone number : \')
if re.match(\'^(13|14|15|18)[0-9]{9}$\',phone_number):
        print(\'是合法的手机号码\')
else:
        print(\'不是合法的手机号码\')

 

 转义符\\

   在正则表达式中,有很多有特殊意义的是元字符,比如\\d和\\s等,如果要在正则中匹配正常的"\\d"而不是"数字"就需要对"\\"进行转义,变成\'\\\\\'。

 在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\\也有特殊的含义,本身还需要转义。所以如果匹配一次"\\d",字符串中要写成\'\\\\d\',那么正则里就要写成"\\\\\\\\d",这样就太麻烦了。这个时候我们就用到了r\'\\d\'这个概念,此时的正则是r\'\\\\d\'就可以了。

r\'\\\\n\' -->r\'\\n\'

四、re模块主要方法

findall 找所有,返回列表
search 找第一个,返回值.group()
match 从开始匹配
split 根据正则表达式去切割
sub/subn 根据正则表达式去替换
compile 编译正则
finditer 找所有,返回迭代器,

1、findall():返回所有符合匹配条件的

import re
ret = re.findall(\'a\', \'eva egon yuan\') # 返回所有满足匹配条件的结果,放在列表里
print(ret)                           #结果 : [\'a\', \'a\']

2、search():在字符串内进行匹配,直到找到第一个后,返回一个包含匹配信息的匹配对象,可以通过group()对匹配对象取出匹配的字符串,如果没有匹配的字符串,则返回None,通过group()取值会报错

import re
ret = re.search(\'a\', \'eva egon yuan\').group()
print(ret)                           #结果 : \'a\'
#search 从左到右依次找,找到一个就回来,需要使用group()获取返回值
如果re.search找不到,就返回None。使用group会报错

3、match():match == ^ 在字符串开头进行匹配,返回一个包含匹配信息的匹配对象,可以通过group()方法调用匹配对象,取出匹配的字符串,如果没有匹配的字符串,则返回None,通过group()取值会报错。

import re
ret = re.match(\'h\', \'abc\')
print(ret)                           #返回None
res = re.match(\'a\', \'abc\')
print(res.group())                  #返回‘a\'
#match从头开始匹配,匹配上了需要使用group来获取返回值
#匹配不上返回None,使用group会报错

4、split():按照正则表达式的要求对字符串分割,返回分割后的列表

import re
ret=re.split(\'[ab]\',\'abcd\')         #先按\'a\'分割得到\'\'和\'bcd\',在对\'\'和\'bcd\'分别按\'b\'分割
print(ret)                          #结果:[\'\',\'bcd\']--->[\'\', \'\', \'cd\']

ret = re.split(\'[ac]\',\'abcd\')
print(ret) # [\'\', \'b\', \'d\']

5、sub():替换字符串中的内容,与字符串方法replace()相似

  replace(old,new,count)

  sub(re,new,str,count)

import re
ret=re.sub(\'\\d\',\'H\',\'av23nb4g4\',2)  #将字符串中的数字替换为\'H’,其中2代表只替换前两个,默认全部替换
print(ret)                          #输出结果:avHHnb4g4

6、subn()替换字符串中的内容,返回一个元组,包含替换结果的字符串及替换次数

import re
ret=re.subn(\'\\d\',\'H\',\'av23nb4g4\')
print(ret)                          #输出结果:(\'avHHnbHgH\', 4)

7、compile

obj = re.compile(\'\\d{3}\')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search(\'abc123eeee\') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group())  #结果 : 123

8、finditer(): 节省内存

import re
ret = re.finditer(\'\\d\', \'ds3sy4784a\')   #finditer返回一个存放匹配结果的迭代器
print(ret)  # <callable_iterator object at 0x10195f940>
print(next(ret).group())  #查看第一个结果
print(next(ret).group())  #查看第二个结果
print([i.group() for i in ret])  #查看剩余的左右结果

 

 计算器

\\d+\\.?\\/\\d*
式子前面必须有,后面可无

import re
#处理符号用的
def dealwith_symbol(express):
    if \'--\' in express:express = express.replace(\'--\',\'+\')
    if \'+-\' in express:express = express.replace(\'+-\',\'-\')
    if \'-+\' in express:express = express.replace(\'-+\',\'-\')
    if \'++\' in express:express = express.replace(\'++\',\'+\')
    return express
#处理乘除法
def mul_div(express):
    #a*b  a/b
    if \'*\' in express:
        a,b = express.split(\'*\')
        ret = float(a)*float(b)
    elif \'/\' in express:
        a, b = express.split(\'/\')
        ret = float(a) / float(b)
    return str(ret)

# 将没有括号的子表达式中的乘除法先提取出来,再计算加减法
def simplify_express(express_son):  #(9-2*5/3)
    while True:  #取乘除法计算
        ret = re.search(r\'\\d+\\.?\\d*[*/]-?\\d+\\.?\\d*\',express_son)   #(9-2*5/3)
        if ret:
            mul_div_express = ret.group()     #2*5
            result = mul_div(mul_div_express)   #10
            express_son = express_son.replace(mul_div_express,result,1)   #(9-3.3)
            express_son = dealwith_symbol(express_son)
        else:break
    express_son = dealwith_symbol(express_son)
    num_lst = re.findall(r\'[\\+\\-]?\\d+\\.?\\d*\',express_son)  #(-8)
    sum = 0
    for i in num_lst:
        sum += float(i)
    return str(sum)

# 1 将表达式中的括号提取出来
def remove_bracket(express):
    #\\([^\\(\\)]+\\)、\\([^\\(]+?\\)、\\([\\-\\d\\+\\/\\*\\.]+\\)
    while True:
        ret  = re.search(r\'\\([^\\(\\)]+\\)\',express)   #  \\([^\\(\\)]+\\)正则表达式
        if ret:
            express_no_bracket = ret.group()  #  express_no_bracket: 没有括号的表达式
            sum = simplify_express(express_no_bracket)
            express = express.replace(express_no_bracket,sum,1)
        else:break
    return simplify_express(express)

e = \'1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )\'
new_express = e.replace(\' \',\'\')  # 去空格
#  1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))
print(new_express)
result = remove_bracket(new_express)
print(result)

 

以上是关于正则,re模块的主要内容,如果未能解决你的问题,请参考以下文章

第43天python学习re模块学习

常用模块-正则re

python成长之路第三篇_正则表达式

python成长之路第三篇_正则表达式

python知识-正则表达式re模块

正则表达式