简介
- 1、一堆带有特殊意思的符号组成的式子它的作用 处理(匹配 查找 替换) 字符串
- 2、在爬虫中大量使用 其实有框架帮你封装了这些复杂的正则
- 3、在网站和手机APP注册功能中大量使用,例如判断你的邮箱地址是否正确
二、正则表达式本身是一种小型的、高度专业化的编程语言,而在python中,通过内嵌集成re模块,
程序媛们可以直接调用来实现正则匹配。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行。
import re re.match #从开始位置开始匹配,如果开头没有则无 re.search #搜索整个字符串 re.findall #搜索整个字符串,返回一个list
精准匹配:
'abc' | abc | 当表达式不包含任何特殊字符 就是精准匹配 说白了判断是否相同 |
单个字符匹配:
换行符 | ||
制表符 | ||
f | 换页符 |
位置匹配:
A | 从字符的开始处匹配 |
从字符结尾处匹配 | |
^ | 从字符的开始处匹配 |
$ | 从字符结尾处匹配 |
范围匹配 判断字符是否在一个范围内:
w | 数字 字母 下划线 |
W | 非数字 字母 下划线 |
d | 数字 |
D | 非数字 |
s | 空白字符 |
S | 非空白字符 |
[...] | 手动指定范围 ascII码表范围 |
[^...] | 指定范围以外的内容 与上面的相反 |
. | 除了换行符之外的任何字符 |
重复匹配:
* | 任意次数 |
+ | 一次或多次 |
? | 0次或一次 |
* + 都是贪婪匹配 会尝试尽可能多取
给表达式加上 ? 变成了非贪婪模式 尽可能的少取 最常用 “w*?”
分组:
给表达是中需要单独获取的部分 加上括号() 'str' = "(http.*?)" 一个表达式中可以有多个分组 用search 或match 得到match对象 调用group 传入组的索引来获取分组内容 ps:如果匹配的内容包含 的变成4个 或者r"\"
正则表达式 - 入门篇
1.元字符
. 匹配除结束符以外的任意字符,某些情况下不能匹配行起始符 ^ 匹配行的开始, 例如 ^The 匹配以The打头的行 $ 匹配行的结束,例如 home$匹配以home结尾的行,^$匹配空行 ? 匹配0或1个任意字符 * 匹配0到任意多个任意字符 + 匹配1到任意多个任意字符 { 量词起始符 } 量词结束符 [ 字符组的起始符 ] 字符组的结束符 转义字符 ( 捕获分组的起始符 ) 捕获分组的结束符 | 用或(or)的方法进行匹配
2. 常用例子
[] 字符组 () 用于捕获分组 {} 表示带查找的字符要重复的次数 {n,} 代表前面的字符可以重复n到无穷多次 {n1,n2} 代表前面的字符可以重复n1到n2次 [0-9] 字符组,匹配数字0-9 [^0-9] 字符组,对[0-9]取反,匹配非数字0-9的任意字符 [+-*-] 字符组,代表加减乘除号
d 数字字符,匹配任意阿拉伯数字,等同于[0-9] D 非数字字符,匹配任何一个非数字字符,即d 取反 w 小写的w 单词字符,匹配字母、数字、下划线,即[_a-zA-Z0-9] W 大写的W 非单词字符,匹配非单词字符,即对小写w取反,即[^_a-zA-Z0-9] a 警告声音输出 退格符 c x 控制符 f 换页符 垂直的制表符 v 小写v 水平的制表符 V 大写V 非水平制表符 h 水平空白符 H 非水平空白符 回车符 换行符 空字符 s 小写s 匹配空白符,即,能匹配空格、制表符 、换行符 、回车符 S 大写S 匹配非空白符,即小写s取反 XXX 字符的八进制值 x xx 字符的十六进制值 u xxx 字符的Unicode值 (?i) 匹配模式时不区分大小写 (?i)the 匹配THE the The 等
2. 举例:捕获分组
将模式放入一对圆括号中,就是将它放进了分组,例如,(d)d
3. 举例:非捕获分组
非捕获分组(Non-capturing Group),不会将内容存储在内存中,因此该分组无法被引用,但也因此性能更好
4. 举例:后向引用
捕获分组后,后面可以用1对捕获的内容进行后向引用,例如,(d)d1,该模式可以匹配数字字符707,101,212, 505, 等等
例子: (?:the|THE|The)
5. 例子若干,自行体会,加强理解
d+.?d* 匹配形如正整数、正小数的字符 -?d+.?d* 匹配形如正整数、负整数、正小数、负小数的字符 [^d+-*/().] 匹配这些字符以外的字符:数字字符、加减乘除号、正反括号、小数点 [+-*/.]{2,} 匹配连续的加减乘除号、小数点 [^()]*([^()]+)[^()]* 匹配配对的括号 (([+-*/]*d+.?d*)+) 匹配最内层括号 (.*)(d+.?d*)([*/])(d+.?d*)(.*) 匹配乘除法表达式 (-?d+.?d*)([+-])(-?d+.?d*)(.*) 匹配加减法表达式
正则表达式 - 进阶篇
1.使用正在表达式为纯文本标签HTML5标签
例如,sed -n 's/^/<h1>/;s/$/</h1>/p;q' rime.txt rime.txt中的文字将以h1格式(即所有字母大写)输出
2. 边界
断言,又称零宽度断言(zero-width assertion),用于标记边界,但不耗用边界上的字符,即字符不会返回到匹配结果中。零宽度断言不匹配字符,而是匹配字符串中的位置。例如^ $,也叫作锚位符(anchor) ^ 匹配行的开始 $ 匹配行的结束 匹配单词边界,表面上会匹配空格或起始行,实际匹配的是零宽度的不存在的东西 B 匹配非单词边界,即 取反,例如,BeB 不会匹配字母e两边的字符,但会识别e两边是否是非单词边界(即,用于标记边界,但不会将边界返回到匹配结果中) 可以用Q和E之间的字符集,匹配字符串的字面值。例如Q$E,会匹配$,而非行结束符,因为Q和E之间的任意字符都会被解释为普通字符。
3. 量词匹配的三种模式:贪心、懒惰、占有
a. 贪心模式:基本量词默认是贪心模式,如?,+,*,{m,n}
首先匹配整个字符串,选定尽可能多的内容,如果匹配失败,就回退一个字符后再次尝试,这个过程叫做回溯(backtracking)。
贪心模式,在匹配时每次回退一个,直到找到匹配的内容或没有字符可尝试为止,较另两种模式而言,贪心模式对资源消耗最大。先“吃”尽所有,然后每次“吐”出一点,慢慢咀嚼消化
b. 懒惰模式: 在普通量词后添加? 量词就成为了懒惰模式
从目标的起始为止开始尝试匹配,每次检查字符串的一个字符,最后才尝试匹配整个字符串。每次只“吃”一点
例子:对于字符串 55678
5? 匹配2个5, 5?? 只匹配到第1个5,前者是贪心模式,后者是懒惰模式
c. 占有模式:在普通量词后添加+ 量词就成为了占有模式
覆盖整个目标后再尝试寻找匹配内容,但只尝试一次,不会回溯,因此速度快。不“咀嚼”而是直接“吞咽”,然后才想知道“吃”的是什么 例子:对于字符串 0000000 0.*+ 匹配到所有的0 .*+0 什么也没匹配到, 前者是占有模式(看起来跟贪心模式一样,但没有回溯,运行更快),后者也是占有模式,因为没有回溯,一下就选定了所有输入,不再回过来查看
4. 环视:正前瞻、反前瞻、正后顾、反后顾
a. 正前瞻: 假设要匹配at,且要求紧随其后的单词是home,要到达这个目的,可以用正前瞻,格式如下: at(?=home) 注意只有模式的第一部分at被标亮了,环视部分(home)不会被标亮 b. 反前瞻:是对正前瞻取反,把=改成! 即 at(?!home) c. 正后顾:查看左边的内容,与正前瞻方向相反,其语法是(?<=at) home,后顾部分(home)会被标亮,条件(at)不会被标亮 d. 反后顾: 对正后顾取反,查看某个模式在从左至右的文本流的后面没有出现,其语法是(?<!at) home,匹配到的结果里没有at
PS:d在javascript中不支持
re模块的使用
1. match(pattern, string, flags=0)
从字符串的开头进行匹配, 匹配成功就返回一个匹配对象,匹配失败就返回None
flags的几种值:
- X 忽略空格和注释
- I 忽略大小写的区别 case-insensitive matching
- S 匹配任意字符,包括新行
def match(pattern, string, flags=0): """Try to apply the pattern at the start of the string, returning a match object, or None if no match was found.""" return _compile(pattern, flags).match(string)
2. search(pattern, string, flags=0)
浏览整个字符串去匹配第一个,未匹配成功返回None
def search(pattern, string, flags=0): """Scan through string looking for a match to the pattern, returning a match object, or None if no match was found.""" return _compile(pattern, flags).search(string)
3. findall(pattern, string, flags=0)
match和search均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。
findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
空的匹配也会包含在结果中
def findall(pattern, string, flags=0): """Return a list of all non-overlapping matches in the string. If one or more capturing groups are present in the pattern, return a list of groups; this will be a list of tuples if the pattern has more than one group. Empty matches are included in the result.""" return _compile(pattern, flags).findall(string)
4. sub(pattern,repl,string,count=0,flags=0)
替换匹配成功的指定位置字符串
def sub(pattern, repl, string, count=0, flags=0): """Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; if a string, backslash escapes in it are processed. If it is a callable, it's passed the match object and must return a replacement string to be used.""" return _compile(pattern, flags).sub(repl, string, count)
5. split(pattern,string,maxsplit=0,flags=0)
根据正则匹配分割字符串
def split(pattern, string, maxsplit=0, flags=0): """Split the source string by the occurrences of the pattern, returning a list containing the resulting substrings. If capturing parentheses are used in pattern, then the text of all groups in the pattern are also returned as part of the resulting list. If maxsplit is nonzero, at most maxsplit splits occur, and the remainder of the string is returned as the final element of the list.""" return _compile(pattern, flags).split(string, maxsplit)
6.compile()
python代码最终会被编译为字节码,之后才被解释器执行。在模式匹配之前,正在表达式模式必须先被编译成regex对象,预先编译可以提高性能,re.compile()就是用于提供此功能。
7. group()与groups()
匹配对象的两个主要方法:
group() 返回所有匹配对象,或返回某个特定子组,如果没有子组,返回全部匹配对象
groups() 返回一个包含唯一或所有子组的的元组,如果没有子组,返回空元组
def group(self, *args): """Return one or more subgroups of the match. :rtype: T | tuple """ pass def groups(self, default=None): """Return a tuple containing all the subgroups of the match, from 1 up to however many groups are in the pattern. :rtype: tuple """ pass