正则表达式
一、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,这些注释会被引擎忽略; 注释用 “#”号 来标识,不过该符号不能在字符串或反斜杠之后。
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 #在匹配部分加上()之后所切出的结果是不同的, #没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项, #这个在某些需要保留匹配部分的使用过程是非常重要的。
贪婪匹配 :默认的 尽可能多匹配
惰性匹配 :需要我们手动设置的 尽可能少匹配
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:修改模式