正则表达式

一、re正则模块

 

  正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。

生活中处处都是正则:

    比如我们描述:4条腿

      你可能会想到的是四条腿的动物或者桌子,椅子等

    继续描述:4条腿,活的

          就只剩下四条腿的动物这一类了

量词
'
.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以 '*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a'] '+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb'] '?' 匹配前一个字符1次或0次 '{m}' 匹配前一个字符m次 '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC' 或的意思 '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c 分组匹配 元字符'\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的 '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] 's' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t'
'\S' 匹配任意非空字符
'\s' 匹配任意空白字符,等价于[\t\n\r\f]
'\G' 匹配最后匹配完成的位置
'\b' 匹配特殊字符边界,字母和空格的边界
'(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}

 正则表达式应用场景:

  场景一 :检测某一段字符串是否符合规则
  场景二 :从某一段文字中找到符合规则的内容

相应的实例:

# =================================匹配模式=================================
#一对一的匹配
# 'hello'.replace(old,new)
# 'hello'.find('pattern')

#正则匹配
import re
#\w与\W   \w表示匹配任意字母和数字以及下划线[A-Z0-9a-z_] \W取反
print(re.findall('\w','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']
print(re.findall('\W','hello egon 123')) #[' ', ' ']
 
#\s与\S  \s 匹配所有的空白空格 本身匹配 空格  \S取反
print(re.findall('\s','hello  egon  123')) #[' ', ' ', ' ', ' ']
print(re.findall('\S','hello  egon  123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']

#\n \t都是空,都可以被\s匹配
print(re.findall('\s','hello \n egon \t 123')) #[' ', '\n', ' ', ' ', '\t', ' ']

#\n与\t \t匹配制表符 table  \n 匹配回车换行
print(re.findall(r'\n','hello egon \n123')) #['\n']
print(re.findall(r'\t','hello egon\t123')) #['\n']

#\d与\D  匹配数字
print(re.findall('\d','hello egon 123')) #['1', '2', '3']
print(re.findall('\D','hello egon 123')) #['h', 'e', 'l', 'l', 'o', ' ', 'e', 'g', 'o', 'n', ' ']

#\A与\Z 匹配大写字母
print(re.findall('\Ahe','hello egon 123')) #['he'],\A==>^
print(re.findall('123\Z','hello egon 123')) #['123'],\Z==>$

#^与$  ^永远在一个规则的最开始,$永远在一个规则的最末尾,^和$ 规定了这个字符串的长度,并且在这个长度内的内容
print(re.findall('^h','hello egon 123')) #['h']
print(re.findall('3$','hello egon 123')) #['3']

# 重复匹配:| . | * | ? | .* | .*? | + | {n,m} |
#.  点匹配换行符之外的所有字符
print(re.findall('a.b','a1b')) #['a1b']
print(re.findall('a.b','a1b a*b a b aaab')) #['a1b', 'a*b', 'a b', 'aab']
print(re.findall('a.b','a\nb')) #[]
print(re.findall('a.b','a\nb',re.S)) #['a\nb']
print(re.findall('a.b','a\nb',re.DOTALL)) #['a\nb']同上一条意思一样

#*   表示匹配0次或多次
print(re.findall('ab*','bbbbbbb')) #[]
print(re.findall('ab*','a')) #['a']
print(re.findall('ab*','abbbb')) #['abbbb']

#?  表示匹配0次或1次
print(re.findall('ab?','a')) #['a']
print(re.findall('ab?','abbb')) #['ab']
#匹配所有包含小数在内的数字
print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']这里的?是说.可有可无

#.*   默认为贪婪匹配 尽可能多的取,在正则中大多数规则都满足贪婪匹配只要满足条件就会取出
print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']

#.*?  为非贪婪匹配:推荐使用 表示尽量取少,于贪婪匹配相反
print(re.findall('a.*?b','a1b22222222b')) #['a1b']
a.*?x 从a开始匹配,匹配任意长度的字符,遇到一个x就立即停止
#+ 表示匹配1次或多次 print(re.findall('ab+','a')) #[] print(re.findall('ab+','abbb')) #['abbb']

#{n} 表示出现n次

#{n,} 表示出现至少n次 #{n,m} 表示出现n-m次 print(re.findall('ab{2}','abbb')) #['abb'] print(re.findall('ab{2,4}','abbb')) #['abb'] print(re.findall('ab{1,}','abbb')) #'ab{1,}' ===> 'ab+' print(re.findall('ab{0,}','abbb')) #'ab{0,}' ===> 'ab*' #[] 字符组[]描述的是一个字符位置上的内容规则,就是在一个字符上选择 print(re.findall('a[1*-]b','a1b a*b a-b')) #[]内的都为普通字符了,且如果-没有被转意的话,应该放到[]的开头或结尾,都可以匹配 print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b'] print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b'] print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]内的^代表的意思是取反,所以结果为['a=b'] print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]内的^代表的意思是取反,所以结果为['a=b'] #\ 转义
print(re.findall('a\\c','a\c')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
print(re.findall(r'a\\c','a\c')) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义 print(re.findall('a\\\\c','a\c')) #同上面的意思一样,和上面的结果一样都是['a\\c']

# \b \b 匹配一个单词的边界,注意需要明确\d的位置,c\b ---> 匹配到abc的c,放在前面\ba则匹配a
n = re.findall(r'I\b','hello,I am a LI#T')  # #也是特殊字符 
print(n) # ['I', 'I']

#[\D\d] [\W\w] [\S\s] 匹配所有

#
[^123]  除了1和2和3之外的都匹配

#| 或
123|456      # 表示123或456
#():分组 
print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab']
print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的ab
print(re.findall('(?:ab)+123','ababab123')) #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容
print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">点击</a>'))#['http://www.baidu.com']
print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">点击</a>'))#['href="http://www.baidu.com"'] #|

print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company') # ['companies', 'company']

re模块的各种方法:

 ===========================re模块提供的方法介绍===========================
import re
#1
print(re.findall('e','alex make love') )   #['e', 'e', 'e'],返回所有满足匹配条件的结果,放在列表里

 ret=re.split("(\d+)","eva3egon4yuan")   #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项
 print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']


#2
print(re.search('e','alex make love').group()) #e,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

#3
print(re.match('e','alex make love'))    #None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match

#4
print(re.split('[ab]','abcd'))     #['', '', 'cd'],先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割 

#5
print('===>',re.sub('a','A','alex make love')) #===> Alex mAke love,不指定n,默认替换所有
print('===>',re.sub('a','A','alex make love',1)) #===> Alex make love
print('===>',re.sub('a','A','alex make love',2)) #===> Alex mAke love
print('===>',re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$',r'\5\2\3\4\1','alex make love')) #===> love make alex

print('===>',re.subn('a','A','alex make love')) #===> ('Alex mAke love', 2),结果带有总共替换的个数

#6
obj=re.compile('\d{2}')

print(obj.search('abc123eeee').group()) #12
print(obj.findall('abc123eeee')) #['12'],重用了obj

subn   ** 替换, 按照正则规则去寻找要被替换掉的内容  返回元组  第二个值是替换的次数
compile ***** 编译一个正则表达式, 用这个结果去search findall match finditer 能够节省时间
finditer***** 返回一个迭代器, 所有的结果都保存着在迭代器内,用的时候通过 循环+group 的方法往外取值 可以节省内存
re.I
    IGNORECASE
    忽略字母大小写

re.L
    LOCALE
    影响 “w, “W, “b, 和 “B,这取决于当前的本地化设置。

re.M
    MULTILINE
    使用本标志后,‘^’和‘$’匹配行首和行尾时,会增加换行符之前和之后的位置。

re.S
    DOTALL
    使 “.” 特殊字符完全匹配任何字符,包括换行;没有这个标志, “.” 匹配除了换行符外的任何字符。

re.X
    VERBOSE
    当该标志被指定时,在 RE 字符串中的空白符被忽略,除非该空白符在字符类中或在反斜杠之后。
    它也可以允许你将注释写入 RE,这些注释会被引擎忽略;
    注释用 “#”号 来标识,不过该符号不能在字符串或反斜杠之后。
re模块 flag参数

 

1.  findall   #会优先显示分组中的内容  取消分组优先 (?:正则)

2.  s = '123alex234wusir'
    ret = re.search('(\d+).*?(\d+)',s)  #group(2)  结果 234
    print(ret.group(1))  # 123
    print(ret.group(2))
    
    ret = re.search('(\d+)\w+(\d+)\w+(\w)',s)
    print(ret.group(1))  # 123
    print(ret.group(2))  # group(2)  结果 4  贪婪匹配
    print(ret.group(3))  # r  贪婪匹配

3. #分组命名  (?P<NAME>正则) 在爬虫时常用: 只适用于match和search,因为findall是列表
    ret = re.search('\d+(?P<name>.*?)\d+',s)
    print(ret.group('name'))  # alex

    # 特殊用法,双端匹配
    ret = re.search('<(?P<tag>\w+)>.*</(?P=tag)>','<h1>wahaha</h2></h1></h3>')
    print(ret.group())  # <h1>wahaha</h2></h1>
    print(ret.group('tag'))   # h1

4. #引用分组  法1:(?P=name)     法二:\1 \2 适用于search和findall
    pattern = r'<(\w+)>(\w+)</(\1)>'
        #\1 直接表示了第一个()里的内容, 这个没有tab,没有组名,直接用数字表达了,但是需要在字符            串前加上一个r, 对\1转义
    ret = re.findall(pattern,'<a>wahaha</a>')
    print(ret)  #[('a', 'wahaha', 'a')]

    s = '<a>wahaha</a>'
    pattern = r'<(\w+)>(\w+)</(\1)>' #\1 直接表示了第一个()里的内容, 这个没有tab,没有组        名,直接用数字表达了,但是需要在字符串前加上一个r, 对\1转义
    ret = re.search(pattern,s)
    print(ret.group())  #<a>wahaha</a>
    print(ret.group(2))   # wahaha

#在匹配部分加上()之后所切出的结果是不同的,
#没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
#这个在某些需要保留匹配部分的使用过程是非常重要的。
re模块方法补充

 

贪婪匹配 :默认的 尽可能多匹配

惰性匹配 :需要我们手动设置的 尽可能少匹配

    a.*  以a开头的任意一个字符串都可以被匹配出来

    a.*?  非贪婪

    a.*?x  从a开始匹配,匹配任意长度的字符,遇到一个x就立即停止

贪婪匹配:a.*x匹配 asdfassddsfsfdxxxxxx时,从a开始会一直匹配到最后一个x
惰性匹配: a.*?x 从a开始匹配,匹配任意长度的字符,遇到一个x就立即停止


贪婪匹配:使用的是回溯算法,下面有回溯算法的示意图。
贪婪匹配原理
import re

ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
#还可以在分组中利用?<name>的形式给分组起名字
#获取的匹配结果可以直接用group('名字')拿到对应的值
print(ret.group('tag_name'))  #结果 :h1
print(ret.group())  #结果 :<h1>hello</h1>

ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
#如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
#获取的匹配结果可以直接用group(序号)拿到对应的值
print(ret.group(1))
print(ret.group())  #结果 :<h1>hello</h1>
补充部分
1. 匹配最里层括号:  \([ ^()] )
2. 匹配在运算表达式字符串中带有负号的数(这个必须用分组括住,不然显示不正确):(-?\d+(?:\.\d+)?)
3. 匹配乘除: \d+(\.\d+)?[*/]-?\d+(\.\d+)? 
匹配注意点

 

1、匹配整数   [1-9]\d*|0
2、匹配小数    \d+\.\d+
3、匹配一个整数或者小数  \d+\.\d+|([1-9]\d*|0)    \d+(\.\d+)?
4、匹配15位或者18位的身份证号码:
    15位     首位不能为0      ^[1-9]\d{14}$
    18位   首位不能为0,末尾可能是x和数字   ^[1-9]\d{16}[\dx]$
    合起来     ^([1-9]\d{16}[\dx]|[1-9]\d{14})$    

重点反斜杠'\'的用法

  与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

# 方法一
ret = re.findall('\\\\',r'adc\n')   # 这里的r是使\n为原生字符串
print(ret)   # ['\\']

# 方法二
ret1 = re.findall(r'\\','adc\s')
print(ret1)  # ['\\']

 相应的代码补充:

import re
print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")) #['h1']
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").group()) #<h1>hello</h1>
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").groupdict()) #<h1>hello</h1>

print(re.search(r"<(\w+)>\w+</(\w+)>","<h1>hello</h1>").group())
print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>").group())
import re
print(re.findall(r'-?\d+\.?\d*',"1-12*(60+(-40.35/5)-(-4*3))")) #找出所有数字['1', '-12', '60', '-40.35', '5', '-4', '3']
  #使用|,先匹配的先生效,|左边是匹配小数,而findall最终结果是查看分组,所有即使匹配成功小数也不会存入结果
  #而不是小数时,就去匹配(-?\d+),匹配到的自然就是,非小数的数,在此处即整数,但是在其实findall匹配到了小数,如下,只是显示空字符
print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出所有整数['1', '-2', '60', '', '5', '-4', '3']

计算器
import re
s2='1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
    # s2='1+2-23*2+(2*3/2-1)+(23*2-1)/5-1*4'
def compute_mul_div(arg):
    ''' 递归计算乘法'''
    val = arg[0]
    mch = re.search('\d+(\.\d+)?[\*\/]+[\+\-]?\d+(\.\d+)?',val)
    if not mch:
        return
    content = re.search('\d+(\.\d+)?[\*\/]+[\+\-]?\d+(\.\d+)?',val).group()
    if len(content.split('*'))>1:
        n1,n2 =content.rsplit('*',1)
        value = float(n1)*float(n2)
    else:
        n1,n2 =content.rsplit('/',1)
        value = float(n1)/float(n2)

    before,after = re.split('\d+(?:\.\d+)?[\*\/]+[\+\-]?\d+(?:\.\d+)?',val,1)
    new_str = '%s%s%s'%(before,value,after)
    arg[0] =new_str
    compute_mul_div(arg)

def compute_add_sub(arg):
    '''操作加减法'''
    while True:
        if arg[0].__contains__('+-') or arg[0].__contains__("++") or arg[0].__contains__\
('-+') or arg[0].__contains__("--"):   # 进行加减号修正
            arg[0]=arg[0].replace('++','+')
            arg[0]=arg[0].replace('+-','-')
            arg[0]=arg[0].replace('-+','-')
            arg[0]=arg[0].replace('--','+')
        else:break
    val = arg[0]
    mch= re.search('\d+(?:\.\d+)?[\+\-]{1}\d+(?:\.\d+)?',val)  # 匹配出加减对象
    if not mch:
        return arg[0]
    content =re.search('[-+]?\d+(?:\.\d+)?[\+\-]{1}\d+(?:\.\d+)?',val).group()
    if len(content.split('+'))>1:
        n1,n2= content.rsplit('+',1)
        value = float(n1)+float(n2)
    else:
        n1,n2= content.rsplit('-',1)
        value = float(n1)-float(n2)
    before, after = re.split('\d+(?:\.\d+)?[\+\-]{1}\d+(?:\.\d+)?', val, 1)  #将对象前后进行分隔
    if before=='-'and str(value)[0] =='-':  # 对相应的 before进行修改
        before =''
    elif before=='+':
        before =''
    new_str= '%s%s%s'%(before,value,after) # 拼接新的字符串
    arg[0]=new_str   # 修正
    compute_add_sub(arg) # 递归

def compute(expression):
    # 计算逻辑函数
    inp=[expression,0]  # 对inp对象进行操作
    compute_mul_div(inp) # 乘除法
    compute_add_sub(inp) # 加减法
    return inp[0]

def exec_bracket(expression,count):
    count += 1  # 用于计算括号打开次数
    if not re.search('\(([\+\-\*\/]*\d+(\.\d+)?){2,}\)',expression):
         return compute(expression)   # 没有括号时计算
    content = re.search('\(([\+\-\*\/]*\d+(?:\.\d+)?){2,}\)', expression).group()  # 得到最内层括号,最内层括号,肯定是能最先配对的
    print('before: ',expression)  # 打印最先状态
    before, nothing, after = re.split('\(([\+\-\*\/]*\d+(?:\.\d+)?){2,}\)', expression, 1)  # 筛选出最除了匹配到的 其他的部分
    content = content[1:len(content)-1]  # 去括号
    ret= compute(content)   #计算括号内数字
    print('%s = %s '%(content,ret))    # 打印括号内结果
    expression = '%s%s%s'%(before,ret,after)   #拼接最新结果
    print('after: %s'%expression)
    print('计算%s次'.center(20,'=')%count)  # 打印开括号结果
    print('\n')
    return exec_bracket(expression,count)  #递归


count = 0
ret = exec_bracket(s2,count)
print('最终结果:%s'%ret)            
计算器作业
# 简单方法
#s = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
#第一步 分步实现 ("2-1*-22+3-10/-5")
    # 1. 实现一个乘除法  两两相乘/相除
    # 2. 实现一个加减法  两两相加/相减
    # 3. 把计算结果 替换原来的表达式
    # 4. 替换完成后 处理整体表达式的符号
    # 5. 五个函数: 计算atom_cal()  format()  mul_div()  add_sub()  cal()
#第二步 去括号 计算括号内的
import re
# s='6+7-5'

# 加减法
def add_sbu(s):
    ret = re.findall('[+-]?\d+(?:\.\d+)?',s)  # 这里的第一个?:是不单独保存这一种情况,第二个?就是要么有要么没有
    # print(ret)
    exp_sum = 0
    for i in ret:
        exp_sum = exp_sum + float(i)

    return exp_sum

# ret = add_sbu(s)
# print(ret)

def formate(s):
    s = s.replace('-+','-')
    s = s.replace('+-','-')
    s = s.replace('--','+')
    s = s.replace("++","+")

    return s

def atom_cal(s):
    if '*'in s:
        a,b = s.split('*')
        return str(float(a)*float(b))
    elif '/'in s:
        a,b = s.split('/')
        return str(float(a)/float(b))

# s = '9/3'
def mul_div(s):
    while True:
        ret = re.search('\d+(\.\d+)?[*/]-?\d+(\.\d+)?',s)
        if ret:
            exp = ret.group()
            res = atom_cal(exp)
            s = s.replace(exp,res)
        else:
            return s

def cal(s):
    s = mul_div(s)
    s = formate(s)
    exe_sum = add_sbu(s)

    return exe_sum

def main(s):
    s = s.replace(re.search('\s',s).group(),'')  #  找出非数字的符号 用‘’代替
    while True:
        ret = re.search('\([^()]+\)',s)
        if ret:
            inner_ = ret.group()
            res = str(cal(inner_))
            s = s.replace(inner_,res)
            s = formate(s)
            print(s)
        else:break
    return cal(s)


s = '1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
print(main(s))
简单版-计算器

 补充误区解答

 


 

 补充

#为何同样的表达式search与findall却有不同结果:
print(re.search('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))").group()) #(-40.35/5)
print(re.findall('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))")) #['/5', '*3']

#看这个例子:(\d)+相当于(\d)(\d)(\d)(\d)...,是一系列分组
print(re.search('(\d)+','123').group()) #group的作用是将所有组拼接到一起显示出来
print(re.findall('(\d)+','123')) #findall结果是组内的结果,且是最后一个组的结果
import re
s='''
http://www.baidu.com
egon@oldboyedu.com
你好
010-3141
'''

#最常规匹配
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('Hello\s\d\d\d\s\d{3}\s\w{10}.*Demo',content)
# print(res)
# print(res.group())  #Hello 123 456 World_This is a Regex Demo
# print(res.span()) #标签(0, 40)
#泛匹配
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('^Hello.*Demo',content)
# print(res.group())

#匹配目标,获得指定数据

# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('^Hello\s(\d+)\s(\d+)\s.*Demo',content)
# print(res.group()) #取所有匹配的内容
# print(res.group(1)) #取匹配的第一个括号内的内容
# print(res.group(2)) #去陪陪的第二个括号内的内容

#贪婪匹配:.*代表匹配尽可能多的字符
# import re
# content='Hello 123 456 World_This is a Regex Demo'
#
# res=re.match('^He.*(\d+).*Demo$',content)
# print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字

#非贪婪匹配:?匹配尽可能少的字符
# import re
# content='Hello 123 456 World_This is a Regex Demo'
#
# res=re.match('^He.*?(\d+).*Demo$',content)
# print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字

#匹配模式:.不能匹配换行符
content='''Hello 123456 World_This
is a Regex Demo
'''
# res=re.match('He.*?(\d+).*?Demo$',content)
# print(res) #输出None

# res=re.match('He.*?(\d+).*?Demo$',content,re.S) #re.S让.可以匹配换行符
# print(res)
# print(res.group(1))

#转义:\

# content='price is $5.00'
# res=re.match('price is $5.00',content)
# print(res)
#
# res=re.match('price is \$5\.00',content)
# print(res)

#总结:尽量精简,详细的如下
    # 尽量使用泛匹配模式.*
    # 尽量使用非贪婪模式:.*?
    # 使用括号得到匹配目标:用group(n)去取得结果
    # 有换行符就用re.S:修改模式

 

posted @ 2018-09-09 15:19  独角兕大王  阅读(265)  评论(0编辑  收藏  举报