正则表达式
正则表达式对字符串的逻辑操作,主要是对字符串的一种过滤,用“元字符” 与“普通字符”组成一个字符串规则对已知的字符串或文本过滤出自己想要的字符串
为什么使用正则:使用正则是为了处理文本数据。如果是简单的文本处理,那使用字符串匹配就可以达到目的,但是这样每一次匹配都要单独写语句来完成,为了更加方便,需要抽象出一种规则,这就是正则表达式的由来。
概念:1.?使用单个字符串来描述匹配一系列符合某个句法规则的字符串 2.?是对字符串操作的一种逻辑公式 3.?应用场景:处理文本和数据 4.?处理过程:一次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;否则匹配失败
Python的正则表达式默认区分大小写。
python re模块
在python中,如果想要使用正则表达式,需要先导入re模块:
import?re普通字符串匹配:
字符串的 startswith 方法表示以指定字符串开头,匹配到则返回True,否则返回False; 字符串的 endswith 方法表示以指定字符串结尾,匹配到则返回True,否则返回False。
>>>?str1?=?' Linux ?Python'>>>?str1.startswith(' Linux ')False>>>?str1.startswith(' Linux ')True>>>?str1.endswith('python')False>>>?str1.endswith('Python')Truere模块的方法:
>>>?re.re.A????????????re.LOCALE???????re.Scanner(?????re测试数据pile(?????re.fullmatch(???re.sre_parse re.ASCII????????re.M????????????re.T????????????re.copyreg??????re.functools????re.sub(re.DEBUG????????re.MULTILINE????re.TEMPLATE?????re.enum?????????re.match(???????re.subn(re.DOTALL???????re.Match(???????re.U????????????re.error(???????re.purge(???????re.template(re.I????????????re.Pattern(?????re.UNICODE??????re.escape(??????re.search(??????re.IGNORECASE???re.RegexFlag(???re.VERBOSE??????re.findall(?????re.split(???????re.L????????????re.S????????????re.X????????????re.finditer(????re.sre_compile
re模块在python3中有这些方法,下面介绍一些常用的方法,通过这些方法进行匹配。
方法参数说明:pattern:匹配的正则表达式 string:要匹配的字符串 flags:标记为,用于控制正则表达式的匹配方式。如:是否区分大小写,多行匹配等等 repl:替换的字符串,也可作为一个函数 count:模式匹配后替换的最大次数,默认0表示替换所有匹配 maxsplit:模式匹配后分割的最大次数,默认0表示不分割re测试数据pile:
将正则表达式编译成正则对象,一次编译即可反复使用,不用每次写匹配规则
用法:re测试数据pile(pattern,?flags=0)示例:
>>>?str1' Linux ?Python'>>>?mm?=?re测试数据pile(r'Python')??????????????#?r表示使用原字符串,不加则需要给特殊字符转义>>>?type(mm)<class?'re.Pattern'>re.match:
从字符串的起始位置匹配,返回匹配对象
用法:re.match(pattern,?string,?flags=0)示例:
第一种方式:引用之前 re测试数据pile() 编译过的对象
>>>?str1' Linux ?Python'>>>?mm re测试数据pile('Python')>>>?mm.match(str1)??????????????#没有匹配到,返回None,因为match是从起始位置匹配>>>?type(mm.match(str1))<class?'NoneType'>
>>>?mm?=?re测试数据pile(r' Linux ')>>>?mm.match(str1)<re.Match?object;?span=(0,?5),?match=' Linux '>>>>?mm.match(str1).group()??????????????#?group()返回匹配到的字符串' Linux '
第二种方式:直接使用 re.match() 匹配
>>>?mn?=?re.match('Python',str1)>>>?mn.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?mn?=?re.match(' Linux ',str1)>>>?mn.group()' Linux 're.search:
在一个字符串中查找匹配
用法:re.search(pattern,string,flags=0)示例:
>>>?str1?=?'python?booknum?=?10000'>>>?mm?=?re.search(r'\d+',str1)>>>?mm<re.Match?object;?span=(17,?22),?match='10000'>>>>?mm.group()'10000'
>>>?str1?=?'python?booknum?=?100000'>>>?mm?=?re.search(r'\d+',str1)>>>?mm.group()'100000're.findall:
找到匹配字符串,返回所有非重复匹配项的列表
用法:re.findall(pattern,string,flags=0)示例:
>>>?str1?=?'c++=1000,java=900,python=800'>>>?mm?=?re.search(r'\d+',str1)>>>?mm.group()'1000'
>>>?mm?=?re.findall(r'\d+',str1)>>>?mm['1000',?'900',?'800']>>>?sum([int(x)?for?x?in?mm])2700re.sub:
替换字符串中每一个匹配的子串后返回替换后的整个字符串
用法:re.sub(pattern,repl,string,count=0,flags=0)示例:
>>>?str1?=?'python?booknum?=?10000'>>>?mm?=?re.sub(r'\d+','10001',str1)????????????#将10000替换为10001>>>?mm'python?booknum?=?10001'
>>>?def?add1(match):????????????????#创建一个自动?+1?的函数...?????val?=?match.group()...?????num?=?int(val)?+?1...?????return?str(num)...?>>>?str1'python?booknum?=?10000'>>>?mm?=?re.sub(r'\d+',add1,str1)>>>?mm'python?booknum?=?10001'>>>?str1?=?'python?booknum?=?999'>>>?mm?=?re.sub(r'\d+',add1,str1)>>>?mm'python?booknum?=?1000'
可以看到,通过函数,每次自动 +1
re.split:根据匹配分割字符串,返回分割字符串组成的列表
用法:re.split(pattern,string,maxsplit=0,flags=0)示例:
>>>?str1?=?'jingdongbook:C?C++?Java?Python'>>>?mm?=?re.split(r':|?',?str1)?????????????#以:和空格作为分割符>>>?mm['jingdongbook',?'C',?'C++',?'Java',?'Python']
>>>?str1?=?'jingdongbook:?C?C++?Java?Python,PHP'>>>?mm?=?re.split(r':|?|,',?str1)???????????????#以:、空格和,作为分割符>>>?mm['jingdongbook',?'',?'C',?'C++',?'Java',?'Python',?'PHP']
正则表达式语法
正则表达式元字符:
补充:
元字符 作用 *? +? ?? 匹配模式为非贪婪匹配 \ 引用编号为num的分组匹配到的字符串 (?P 分组取一个别名为name (?P=name) 引用别名为name的分组匹配字符串注意:
[] 中只有 ^,-,\ 三个特殊字符,其中 \ 代表转义字符,其它的都代表原本普通的字符。要使用元字符本身的普通字符,请使用转义字符转义一下。
示例1:. 匹配任意字符,除了换行符 \n
>>>?a?=?re.match(r'a','b')>>>?type(a)<class?'NoneType'>??????????????#说明没有匹配到
>>>?a?=?re.match(r'.','b')>>>?type(a)<class?'re.Match'>>>>?a.group()'b'
>>>?a?=?re.match(r'{.}','{b}')>>>?a.group()'{b}'示例2:
[...] 用来表示一组字符,如 [abc] 表示匹配 'a' 或 'b' 或 'c'
>>>?a?=?re.match(r'{[abcde]}','{a}')>>>?a.group()'{a}'
>>>?a?=?re.match(r'{[abcde]}','{ad}')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'示例3:
\w 匹配字母数字下划线; \W 匹配非字母数字下划线
>>>?a?=?re.match(r'{[\w]}','{a}')>>>?a.group()'{a}'
>>>?a?=?re.match(r'{[\w]}','{?}')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?a?=?re.match(r'{[\W]}','{?}')>>>?a.group()'{?}'
>>>?a?=?re.match(r'[[\w]]','[a]')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?a?=?re.match(r'\[[\w]\]','[a]')?????????????#在匹配带[]的字符串是,需要对[]进行转义>>>?a.group()'[a]'示例4:
* 匹配0个或多个前面的表达式
>>>?a?=?re.match(r'[A-Z][a-z]','Aa')>>>?a.group()'Aa'
>>>?a?=?re.match(r'[A-Z][a-z]','A')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?a?=?re.match(r'[A-Z][a-z]*','A')>>>?a.group()'A'>>>?a?=?re.match(r'[A-Z][a-z]*','Auirwehgiu')>>>?a.group()'Auirwehgiu'>>>?a?=?re.match(r'[A-Z][a-z]*','Au123')????????????????#以数字开头的字符串也会返回None>>>?a.group()'Au'示例5:
+ 匹配1个或多个前面的表达式; ? 匹配0个或1个前面的表达式
>>>?a?=?re.match(r'[_a-zA-Z]+[_\w]*','Au123')>>>?a.group()'Au123'>>>?a?=?re.match(r'[_a-zA-Z]+[_\w]*','_Au123')>>>?a.group()'_Au123'
>>>?a?=?re.match(r'[1-9]?[0-9]?[0-9]','100')>>>?a.group()'100'>>>?a?=?re.match(r'[1-9]?[0-9]?[0-9]','999')>>>?a.group()'999'>>>?a?=?re.match(r'[1-9]?[0-9]?[0-9]','9')>>>?a.group()'9'
>>>?a?=?re.match(r'[1-9]?[0-9]?[0-9]','099')>>>?a.group()'09'>>>?a?=?re.match(r'[1-9]?[0-9]?[0-9]','009')>>>?a.group()'00'示例6:
{n} 精确匹配n个前面的表达式; {n,m} 匹配n到m次前面的表达式
>>>?a?=?re.match(r'[a-zA-Z0-9]{6}@163测试数据','abc123@163测试数据')>>>?a.group()'abc123@163测试数据'>>>?a?=?re.match(r'[a-zA-Z0-9]{6}@163测试数据','abc1234@163测试数据')>>>?a.group()???????????????#?python3中,不满足匹配要求直接返回NoneTraceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'>>>?a?=?re.match(r'[a-zA-Z0-9]{6}@163测试数据','abc12_@163测试数据')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?a?=?re.match(r'[a-zA-Z0-9]{6,10}@163测试数据','abc1234@163测试数据')>>>?a.group()'abc1234@163测试数据'>>>?a?=?re.match(r'[a-zA-Z0-9]{6,10}@163测试数据','lzx Linux @163测试数据')>>>?a.group()'lzx Linux @163测试数据'>>>?a?=?re.match(r'[a-zA-Z0-9]{6,10}@163测试数据','lzxlzxlzxlzx@163测试数据')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'示例7:
*? 、 +? 、 ?? 匹配模式变为非贪婪,尽可能少匹配前面的表达式
>>>?a?=?re.match(r'[0-9][a-z]*','1ab')>>>?a.group()'1ab'>>>?a?=?re.match(r'[0-9][a-z]*?','1ab')?????????????#?*最少匹配0次,因此只匹配0次>>>?a.group()'1'>>>?a?=?re.match(r'[0-9][a-z]+?','1ab')?????????????#?+最少匹配1次,因此只匹配1次>>>?a.group()'1a'>>>?a?=?re.match(r'[0-9][a-z]??','1ab')?????????????#??最少匹配0次,因此只匹配0次>>>?a.group()'1'示例8:
^ 匹配字符串的开头; $ 匹配字符串的结尾
>>>?a?=?re.match(r'^ Linux [\w]*',' Linux @163测试数据')>>>?a.group()' Linux '>>>?a?=?re.match(r'^ Linux [\w]*',' Linux 163_com')>>>?a.group()' Linux 163_com'>>>?a?=?re.match(r'^ Linux [\w]*','l Linux 163_com')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?a?=?re.match(r'[\w]{6,10}@163测试数据','lzx Linux @163测试数据')>>>?a.group()'lzx Linux @163测试数据'>>>?a?=?re.match(r'[\w]{6,10}@163测试数据','lzx Linux @163测试数据abc')>>>?a.group()'lzx Linux @163测试数据'>>>?a?=?re.match(r'[\w]{6,10}@163测试数据$','lzx Linux @163测试数据abc')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'>>>?a?=?re.match(r'[\w]{6,10}@163测试数据$','lzx Linux @163测试数据')>>>?a.group()'lzx Linux @163测试数据'示例9:
\A 匹配指定字符串开头; \Z 匹配指定字符串结尾,不匹配换行符 \n
>>>?a?=?re.match(r'\A Linux [\w]*',' Linux @163测试数据')>>>?a.group()' Linux '>>>?a?=?re.match(r'\A Linux [\w]*','m Linux @163测试数据')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
>>>?a?=?re.match(r'[\w]{6,10}@163测试数据\Z','lzx Linux @163测试数据')>>>?a.group()'lzx Linux @163测试数据'>>>?a?=?re.match(r'[\w]{6,10}@163测试数据\Z','lzx Linux @163测试数据abc')>>>?a.group()Traceback?(most?recent?call?last): ??File?"",?line?1,?in?<module>AttributeError:?'NoneType'?object?has?no?attribute?'group'
区别 :
^? 指定匹配必须出现在字符串的开头或行的开头。 \A? 指定匹配必须出现在字符串的开头(忽略?Multiline?选项)。? $? 指定匹配必须出现在以下位置:字符串结尾、字符串结尾的?\n?之前或行的结尾。? \Z? 指定匹配必须出现在字符串的结尾或字符串结尾的?\n?之前(忽略?Multiline?选项)。示例10:
() 匹配括号中的表达式,或者括号中的表达式作为一个分组; \ 引用编号为num的分组匹配到的字符串
>>>?a?=?re.match(r'[\w]{6,10}@(163|126)测试数据$','lzx Linux @163测试数据')>>>?a.group()'lzx Linux @163测试数据'>>>?a?=?re.match(r'[\w]{6,10}@(163|126)测试数据$','lzx Linux @126测试数据')>>>?a.group()'lzx Linux @126测试数据'
>>>?a?=?re.match(r'','')>>>?a.group()''>>>?a?=?re.match(r')','')>>>?a.group()''>>>?a?=?re.match(r')\1','book>')>>>?a.group()'book>'???????????????#?\1?等同于?book>>>>?a?=?re.match(r')[\w]+,'python')>>>?a.group()'python'???????????????#这种匹配可抓取有效的xml示例11:
(?P 给分组取一个别名为name; (?P=name) 引用别名为name的分组匹配字符串
>>>?a?=?re.match(r'<(?P[\w]+>)[\w]+,'python')>>>?a.group()'python'
这里的 ?P 是给分组取别名为 Linux ,而 (?P= Linux ) 是引用别名,等同于上面的 \1 。
取别名可以让有多个分组的正则表达式更好的引用。