正则表达式

1.正则概念

正则表达式也叫作匹配模式,是由一组具有特殊含义的字符组成,通常是用来匹配和替换字符串,它是一门独立技术,用途的话,比如爬网页提取图片和文字啥的,使用正则表达式可使用正则模块“re”,引入的话可以使用以下带代码

import re

2.1.正则匹配

匹配和替换和正则表达式的主要功能,所以而替换的前提是匹配,所以正则表达式中,涉及到匹配的match方法和search方法,将是众多其他方法使用的前提,必须熟练掌握。

2.1.1.match方法

描述尝试从字符串的起始位置进行匹配,如果不是起始位置匹配成功的话,match() 就返回 none,否则就返回一个匹配对象。

函数语法

re.match(pattern, string, flags=0)

函数参数说明

参数描述
pattern匹配的正则表达式
string要匹配的字符串。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

举例说明

> s1 = "my name is xuquanwen"
>>> m1 = re.match("my",s1)
>>> m2 = re.match("is",s1)
>>> print(m1)
<re.Match object; span=(0, 2), match='my'>
>>> print(m2)
None
>>>

就像之前描述的那样,“my”字符串位于s1字符串中匹配到的第一个,所以返回了一个对象给m1,而"is"字符串位于s1字符串中匹配到的第三个所以返回空也就是None.

2.1.2.匹配对象使用

当然match方法匹配到的对象肯定是要使用的,它的使用方法则可以使用分组中的group(num) 或 groups() 匹配对象函数来获取匹配表达式。这里也会简单先提一下“位数”和“元字符”等概念,不过下文也会更详细讲述。

匹配对象方法描述
group(num=0)匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups()返回一个包含所有小组字符串的元组,从 1 到 所含的小组号

举例说明

>>> m3 = re.match("(.*) (.*) (.*) (.*)",s1)
>>> m3.group()
'my name is xuquanwen'
>>> m3.group(1)
'my'
>>> m3.group(2)
'name'
>>> m3.group(3)
'is'
>>> m3.group(4)
'xuquanwen'
>>> m3.groups()
('my', 'name', 'is', 'xuquanwen')
>>>

*这里简单解释下上述代码,此处使用“(. * ) (. * )”表示分组,有两个括号间的空格来加以分割,"."的意义表示除了换行符外任意字符,则表示任意多个,简单来说就是用单独匹配出每个单词,group()默认值参数为0,即输出整个字符串。

2.1.3.search方法

描述:re.search 扫描整个字符串并返回第一个成功的匹配。

函数语法

re.search(pattern, string, flags=0)

函数参数说明

参数描述
pattern匹配的正则表达式
string要匹配的字符串。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

参数和match没啥区别,只不过match匹配条件是否是第一个,即严格要求条件为匹配字符串必须是被匹配字符串的子串,且匹配子串必须从被匹配字符串的头部开始。而search则是只要有子串就能匹配成功,同样的匹配成功re.search方法返回一个匹配的对象,否则返回None。

老规矩举例说明

>>> s = re.search("is",s1)
>>> s
<re.Match object; span=(8, 10), match='is'>
>>> s.group()
'is'
>>> s = re.search("sfsd",s1)
>>> s
>>> print(s)
None
>>>

通过上述代码可知,re.search仅仅只是匹配是否子串而已,比match无疑要宽松很多。刚刚我们也讲了可以用分组的方法使用match方法的匹配对象,对于search方法的匹配对象同样适用。

>>> s3 = re.search("(.*) (.*) (.*) .*",s1)
>>> s3.group()
'my name is xuquanwen'
>>> s3.group(1)
'my'
>>> s3.group(2)
'name'
>>> s3.group(3)
'is'
>>> s3.group(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: no such group
>>> s3.groups()
('my', 'name', 'is')
>>>

匹配方法就简单讲述到这里,下面我们看看其他几个检索和替换的方法。

3.正则检索和替换

个人才疏学浅用的少,主要还是用在爬网页中把html代码干掉。其他用处就不知道(暂时)了。学爬虫的话,反正是有用的。

3.1.sub方法

描述:sub方法的话主要用在替换字符串中。

语法

re.sub(pattern, repl, string, count=0, flags=0)

参数

参数功能
pattern正则中的模式字符串。
repl替换的字符串,也可为一个函数。
string要被查找替换的原始字符串。
count模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
>>> sss
'<body><ul><li><a href="#">友情链接</a></li><li><a href="#">友情链接</a></li><li
><a href="#">友情链接</a></li><li><a href="#">友情链接</a></li><li><a href="#">
友情链接</a></li><li><a href="#">友情链接</a></li></ul></body>'
>>> re.sub("</?.+?>","",sss)
'友情链接友情链接友情链接友情链接友情链接友情链接'

4.正则表达式符号

即用来表示字符类型的字符

4.1.元字符

格式作用
\d匹配数字
.匹配任意符号除了换行符
\w匹配所有有效符号(大小写字母、数字、下划线、各国语言符号)
\s匹配空白位(空格、\t)
^匹配以XXX开头 例如:以1开头 ^1
$以XXX结尾
[]列举 [0123456789] 等价于 \d [a-z]表示所有小写字母 [A-Za-z0-9]表示所有有效字符,[A-Za-z]表示大小写字母
>>> import re
>>> re.match(".","1")
<re.Match object; span=(0, 1), match='1'>
>>> re.match(".","\n")
>>> re.match("...","abc")
<re.Match object; span=(0, 3), match='abc'>
>>> re.match("...","abcdef")
<re.Match object; span=(0, 3), match='abc'>
>>> re.match(".","\rabcdef")
<re.Match object; span=(0, 1), match='\r'>
>>> re.match("\d","a")
>>> re.match("\d","5")
<re.Match object; span=(0, 1), match='5'>
>>> re.match("\d","5567")
<re.Match object; span=(0, 1), match='5'>
>>> re.match("\d\d","5567")
<re.Match object; span=(0, 2), match='55'>
>>> re.match("\w","5")
<re.Match object; span=(0, 1), match='5'>
>>> re.match("\w","_")
<re.Match object; span=(0, 1), match='_'>
>>> re.match("\w","&")
>>> re.match("\w","^")
>>> re.match("\s"," ")
<re.Match object; span=(0, 1), match=' '>
>>> re.match("\s","\t\t")
<re.Match object; span=(0, 1), match='\t'>
>>> re.match("^1","123")
<re.Match object; span=(0, 1), match='1'>
>>> re.match("^1","212")
>>> re.match("^1.*","aaaaffff")
>>> re.match("^1.*","1aaaaffff")
<re.Match object; span=(0, 9), match='1aaaaffff'>
>>> re.findall("^1","aaaffff")
[]
>>> re.findall("^1","aaaff12ff")
[]
>>> re.findall("^1","12aaaff12ff")
['1']
>>> re.findall("^1.*","12aaaff12ff")
['12aaaff12ff']
>>> re.match("^1\d*","18")
<re.Match object; span=(0, 2), match='18'>
>>> re.match("^1\d*$8","18")
>>> re.match("^1\d*8$","18")
<re.Match object; span=(0, 2), match='18'>
>>> re.match("8$","18")
>>> re.match("$8","18")
>>> re.match("[12345678]","18")
>>>> re.match("[a-z]","ttt")
<re.Match object; span=(0, 1), match='t'>
>>> re.match("[a-z]*","ttt")
<re.Match object; span=(0, 3), match='ttt'>
>>> re.match("[a-z]*","tsdfsfdasdas")
<re.Match object; span=(0, 12), match='tsdfsfdasdas'>
>>> re.match("[A-Z]*","WORLD")
<re.Match object; span=(0, 5), match='WORLD'>
>>> re.match("[A-Za-z]*","WORLD love nature")
<re.Match object; span=(0, 5), match='WORLD'>
>>> re.match("[A-Za-z]*","WORLDlovenature")
<re.Match object; span=(0, 15), match='WORLDlovenature'>
>>> re.match("[A-Za-z0-9]*","WORLDlovenature1998")
<re.Match object; span=(0, 19), match='WORLDlovenature1998'>
>>> re.match("[0-9A-Za-z]*","WORLDlovenature1998")
<re.Match object; span=(0, 19), match='WORLDlovenature1998'>
>>> re.match("[0-9a-zA-z]*","WORLDlovenature1998")
<re.Match object; span=(0, 19), match='WORLDlovenature1998'>
<re.Match object; span=(0, 1), match='1'>
>>> re.match("我今年\d岁了","我今年18岁了")
>>>
>因为\d只会匹配数字

4.2 反义符

格式作用
\D不是数字
\W特殊符号
\S非空白位
>>> re.match("\D","2")
>>> re.match("\D","ee")
<re.Match object; span=(0, 1), match='e'>
>>> re.match("\W","ee")
>>> re.match("\W","^")
<re.Match object; span=(0, 1), match='^'>
>>> re.match("\S"," ")
>>> re.match("\S","sd")
<re.Match object; span=(0, 1), match='s'>

注意:[ ^ ]-------- 列举反义 注意 ^ []和 [ ^ ]的区别

4.3 转义符

在python中如果字符串中含有\是具有特殊含义的,如果要表示一个正常等等\n,需要有两个\

>>> s = "hello\n world "
>>> s
'hello\n world '
>>> print(s)
hello
 world
>>> s = "hello\\n world "
>>> print(s)
hello\n world
>>>

在正则里表达式中反斜杠是有特殊含义的,如果要表示一个正常的反斜杠需要两个反斜杠表示

>>> re.match("C:\\a\\b\\c",path)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "E:\py\lib\re.py", line 191, in match
    return _compile(pattern, flags).match(string)
  File "E:\py\lib\re.py", line 304, in _compile
    p = sre_compile.compile(pattern, flags)
  File "E:\py\lib\sre_compile.py", line 764, in compile
    p = sre_parse.parse(p, flags)
  File "E:\py\lib\sre_parse.py", line 948, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
  File "E:\py\lib\sre_parse.py", line 443, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
  File "E:\py\lib\sre_parse.py", line 525, in _parse
    code = _escape(source, this, state)
  File "E:\py\lib\sre_parse.py", line 426, in _escape
    raise source.error("bad escape %s" % escape, len(escape))
re.error: bad escape \c at position 6
>>> re.match("C:\\\\a\\\\b\\\\c",path)
<re.Match object; span=(0, 8), match='C:\\a\\b\\c'>
>>>

这里正则转义一次

>>> s = "\\\\\\"
>>> s
'\\\\\\'
>>> print(s)
\\\

可用r表示正则

>>> re.match(r"C:\\a\\b\\c",path)
<re.Match object; span=(0, 8), match='C:\\a\\b\\c'>

建议大家在正则使用中加上r

5 位数

即在指定正则生效的实际范围

>>> s = "我今年18,明年19"
>>> s
'我今年18,明年19'
>>> re.findall(r"\d",s)
['1', '8', '1', '9']
>>> re.findall("\d",s)
['1', '8', '1', '9']

后面加*表示匹配任意位
后面加+表示至少有一位,可以有n位
? 表示0位或者1位
{n,} 至少n位i
{n,m} n到m的区间,m可以超出最大值

>>> re.findall(r"1[356789]\d{7,}","133456789")
['133456789']
>>> re.findall(r"1[356789]\d{6,}","133456789")
['133456789']
>>> re.findall(r"1[356789]\d{1,2}","1334567891")
['1334']
>>> re.findall(r"1[356789]\d{1,8}","1334567891")
['1334567891']
>>> re.findall(r"1[356789]\d{1,7}","1334567891")
['133456789']
>>> re.findall(r"1[356789]\d{1,9}","1334567891")
['1334567891']
>>> re.findall(r"1[356789]\d{1,10}","1334567891")
['1334567891']


需要提一下的是?,其作为非贪婪匹配可以如下组合’a*?',即匹配遇到的第一个a,而如果是’a*'则会直接匹配到最后一个a.

6.分组

正则表达式中,使用()将正则包裹起来,形成一个分组,目的是为了匹配后的二次匹配

>>> s = "我今年18,我明年23"
>>> import re
>>> res = re.match(r".*(\d)+.*",s)
>>> res
<re.Match object; span=(0, 11), match='我今年18,我明年23'>
>>> res.group(1)
'3'
>>> res.group(0)
'我今年18,我明年23'
>>> res.group(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: no such group
>>> res = re.match(r".*?(\d+).*",s)
>>> res.group(1)
'18'
>>> res.group(0)
'我今年18,我明年23'

>>> res = re.match(r"(\d{4})-(\d{4})","1234-5678")
>>> res
<re.Match object; span=(0, 9), match='1234-5678'>
>>> res.group()
'1234-5678'
>>> res.group(1)
'1234'
>>> res.group(2)
'5678'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值