一、正则表达式的概念:
正则表达式是记录文本规则的代码
1.元字符:元字符是一个或者一组代替一个或者多个字符的字符
例子:元字符*用来匹配0个或多个的前一字符;而元字符 . 用来匹配一个任意的一个字符。
代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
元字符 ^ 和 $ 都匹配一个位置,这和\b有点类似,^ 匹配你要用来查找的字符串的开头,$ 匹配结尾:输入5位到12位数字==> ^\d{5,12}$
2.字符转义
如果你想查找元字符本身的话,比如你要找 . 或者 * 就出现了问题:你没办法指定他们本身,因为他们会本解释成别的意思,这时你就要使用 \ 来取消这些字符的特殊含义。因此,你应该使用 \. 和 \* 。当然,要查找\本身,你也得用 \\ 。
3.重复
代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
例子:
m\d+ 匹配m后面跟1个或者更多数字
^\w+ 匹配一行的第一个单词(或者整个字符串的第一个单词)
4.字符类
\(?0\d{2}[) -]?\d{8}
分析:
- 转义字符\(,它出现0次或者1次(?)
- 接着是一个0
- 接着是2个数字(\d{2})
- 接着是 ) 或者 - 或者空格,它出现的额次数是0次或者1次
- 最后是八个数字(\d{8})
5.分组
要重复多个字符,可以用小括号来指定子表达式(也叫分组)
IP:
^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
^表示开头
25[0-5]|2[0-4]\d|[0-1]?\d?\d ==》
25[0-5] :百位是2,十位是5,个位是0到5的任意数
2[0-4]\d:百位是2,十位是0到4的任意数数,个位是0到9任意数
[0-1]?\d?\d:百位是0或者1或者没有,十位可以有也可以没有,个位是0到9的任意数
{3}:表示这个符号之前的组出现3次
$表示结尾
手机号:
^1[3|4|5|7|8][0-9]\d{8}$
^1:表示以1开头
[3|4|5|7|8]:表示第二位可能是3、4、5、7、8中的任意一个数
[0-9]:第三位表示是0到9的任意数
\d{8}:最后是8个数字
$:表示结尾
6.反义
代码/语法 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符
例子:
\S+:匹配不包含空白符的字符串
<a[^>]+>:匹配用尖括号括起来以a开头的字符串
7.贪婪与懒惰
代码/语法 说明
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
例:
a.*b它将匹配以a开头b结尾的字符串,如果来搜索aabab的话它会拿到整个字符串===贪婪匹配
a.*?b匹配最短的以a开始以b结束,如果搜索aabab的话它的结果是aab===懒惰匹配
二、函数
1.match(pattern,string,flag=0)
从起始位置开始根据数据模型去字符串中匹配指定的内容,匹配单个
import re
m = re.match('\d+','12345wewewd')
print(m.group())
结果:
123
flags:
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解
2.search(pattern,string,flags=0)
根据模型去字符串中匹配指定内容,匹配单个
import re
m = re.match('\d+','um12345wewewd')
print(m.group())
结果:
123
3.group和groups
a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group())
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups())
结果:
123abc456
123abc456
123
abc
('123', 'abc', '456')
4.findall(pattern,string,flags=0)
上面的两个式子都是用来匹配单个的值,即只能匹配字符串中的一个,如果想匹配字符串中所有符合条件的元素则需要用findall
m = re.findall('\d+','123ddee343efgdgg55r6r')
print(m)
结果:
['123', '343', '55', '6']
注:findall的结果返回的是一个列表
5.sub(pattern, repl, string, count=0, flags=0)
用于替换匹配的字符串
s = "123wdjwd456rte"
n_s = re.sub('\d+','python',s,1)
print(n_s)
结果:
pythonwdjwd456rte
注:1表示是替换的次数
6.split(pattern, string, maxsplit=0, flags=0)
根据指定匹配进行分组
content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
new_content = re.split('\*', content)
# new_content = re.split('\*', content, 1)
print new_content
content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
new_content = re.split('[\+\-\*\/]+', content)
# new_content = re.split('\*', content, 1)
print new_content
inpp = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))'
inpp = re.sub('\s*','',inpp)
new_content = re.split('\(([\+\-\*\/]?\d+[\+\-\*\/]?\d+){1}\)', inpp, 1)
print new_content