正则表达式

文章目录

1.正则概念

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

bash 复制代码
import re

2.1.正则匹配

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

2.1.1.match方法

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

函数语法

bash 复制代码
re.match(pattern, string, flags=0)

函数参数说明

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

举例说明

bash 复制代码
> 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 到 所含的小组号

举例说明

python 复制代码
>>> 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 扫描整个字符串并返回第一个成功的匹配。

函数语法

python 复制代码
re.search(pattern, string, flags=0)

函数参数说明

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

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

老规矩举例说明

bash 复制代码
>>> 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方法的匹配对象同样适用。

bash 复制代码
>>> 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方法的话主要用在替换字符串中。

语法

bash 复制代码
re.sub(pattern, repl, string, count=0, flags=0)

参数

参数 功能
pattern 正则中的模式字符串。
repl 替换的字符串,也可为一个函数。
string 要被查找替换的原始字符串。
count 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
python 复制代码
>>> 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]表示大小写字母
python 复制代码
>>> 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 非空白位
python 复制代码
>>> 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,需要有两个\

python 复制代码
>>> s = "hello\n world "
>>> s
'hello\n world '
>>> print(s)
hello
 world
>>> s = "hello\\n world "
>>> print(s)
hello\n world
>>>

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

python 复制代码
>>> 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'>
>>>

这里正则转义一次

python 复制代码
>>> s = "\\\\\\"
>>> s
'\\\\\\'
>>> print(s)
\\\

可用r表示正则

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

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

5 位数

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

python 复制代码
>>> 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可以超出最大值

python 复制代码
>>> 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.分组

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

python 复制代码
>>> 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'
python 复制代码
>>> 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'
相关推荐
测开小菜鸟21 分钟前
使用python向钉钉群聊发送消息
java·python·钉钉
萧鼎2 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸2 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农2 小时前
Python 继承、多态、封装、抽象
开发语言·python
Python大数据分析@2 小时前
python操作CSV和excel,如何来做?
开发语言·python·excel
黑叶白树2 小时前
简单的签到程序 python笔记
笔记·python
Shy9604182 小时前
Bert完形填空
python·深度学习·bert
上海_彭彭3 小时前
【提效工具开发】Python功能模块执行和 SQL 执行 需求整理
开发语言·python·sql·测试工具·element
zhongcx013 小时前
使用Python查找大文件的实用脚本
python
yyfhq4 小时前
sdnet
python