正则表达式,缩写微微regex regexp RE等
正则表达式是处理文本极为重要的技术,用它可以对字符串按照某种规则进行检索
是1970 unix之父ken thompson将正则表达式引入到unix中文本编辑器ed和grep命令中
1980年 perl语言对henry spencer编写的库,扩展了很多新的特性,1997年开始开发出了PCRE,被PHP和HTTPD广泛使用
shell中处理文本命令,各种高级编程语言都支持正则表达式
BRE
基本正则表达式 grep sed vi等软件支持,,vim有扩展
ERE
扩展正则表达式,egrep ( grep-E ) ,sed - r等
PCRE
几乎所有语言都是PCRE的方言或者变种,python使用SRE正则表达式引擎,可以认为是PCRE的子集,模块为re
基本语法:
元字符
|
说明
|
举例
|
.
|
匹配除换行符外地所有字符
|
.
|
[abc]
|
字符范围,只能匹配一个位置的对应任意一个字符
|
[abc]匹配plain中的 'a'
|
[^abc]
|
字符范围,匹配除指定字符以外的任何一位字符的一个位置
|
[^abc]匹配plain中的 p l i n
|
[a-z]
|
字符范围,表示任意一个字符的字符位置
|
常用[a-z][0-9]
|
匹配单词的边界
|
b在文本中找到单词b开头的b字符
|
|
B
|
不匹配单词的边界
|
tB包含t的单词但是不以t结尾的t字符,例如write
Bb,不以b开头的含有b的单词,如able
|
d
|
[0-9]匹配1位数字
|
d
|
D
|
[^0-9匹配一位非数字
|
|
s
|
匹配1位空白字符,包括换行符,制表符,空格
[f
v]
|
|
S
|
匹配一位非空白字符
|
|
w
|
匹配[a-z0-9A-Z_],包括中文字符
|
w
|
W
|
匹配w之外的字符
|
|
单行模式:
. 可以匹配任意字符,包括换行符
^ 表示整个字符串的开头,$整个字符串的结尾
多行模式:
. 可以匹配除了换行符之外的字符
^ 表示行首,$行尾
^ 表示整个字符串的开始, ^表示整个字符串的结尾,开始指的是
后的第一个字符,结束指的是
前段哪一个字符
windows中 会有
存在,会干扰$的测试
转义
凡是在正则表达式中有特殊意义的符号,如果想要使用它的本意,使用 转义,反斜杠自身也可以被转义,使用 \
、
还是转义后代表回车,换行
重复
代码
|
说明
|
举例
|
*
|
表示前面的正则表达式会重复 0次到多次
|
ew*单词中有e然后后面非空白字符
|
+
|
表示前面的正则表达式会重复 1次到多次
|
ew+单词中有e且后面至少有一个空白字符
|
?
|
表示前面的正则表达式会重复 0次到1次
|
ew?单词中有e且后面最多有一个空白符
|
{n}
|
重复固定的n次
|
ew{1} 匹配1次
|
{n,}
|
重复n到无限次
|
ew{1} 1到无限次
|
{n,m}
|
重复n到m的次数
|
ew{1,3} 匹配至少1,至多3次
|
代码
|
说明
|
举例
|
x|y
|
匹配x或者y
|
wood took foot food
使用w|ood或者(w|f)ood
|
捕获(分组)
|
|
|
(pattern)
|
使用小括号指定一个子表达式,也叫分组,捕获后会自动分配组号从1开始可以改变优先级
|
|
数字
|
匹配对应的分组,注意括号后有一个空格
|
(very)1 匹配very very,但捕获的组是groupvery
|
(?:pattern)
|
如果为了改变优先级,就不需要捕获分组
|
(?:w|f)ood 例如go(?:od|d)等价于good|god
|
(?<name>exp)
(?'name'exp)
|
分组捕获,但是可以通过name访问分组python语法必须是(?P,name>exp)
|
|
零宽断言
|
|
|
(?=exp)
|
断言exp一定在匹配的右边出现
|
f(?=oo) f后面一定有oo出现
|
(?<=exp)
|
断言匹配左边一定有exp出现
|
(?<=f)ood ood左边一定要有f出现
|
负向零宽断言
|
|
|
(?!exp)
|
断言exp一定不会出现在匹配的右侧
|
d{3}(?!d),断言在三位数字后一定不能是数字
|
(?<!exp)
|
断言exp一定不出出现在匹配的左侧
|
(?<!f)ood ood的左边一定不能出现f
|
注释;
|
|
|
(?#comment)
|
注释
|
f(?=oo)(?#这是个右断言,不分组)
|
分组和捕获是同一个意思
能用简单的表达式,就不用复杂的表达式
贪婪与非贪婪
默认贪婪模式,也就是说尽量多匹配更长的字符串
非贪婪很简单,在重复的符号后面加上一个 ? ,就尽量的少匹配了
代码
|
说明
|
*?
|
匹配任意次,但尽量少重复
|
+?
|
最少匹配1次,但尽量少重复
|
{n,}?
|
最少匹配n次,但尽量少重复
|
{n,m}?
|
最少匹配n次,最多匹配m次,但尽量少重复
|
引擎选项
代码
|
说明
|
python
|
IgonreCase
|
匹配时忽略大小写
|
re.I
re.IGNORECASE
|
Singleline
|
单行模式 : . 可以匹配所有字符,包括
|
re.S
re.DOTALL
|
Multiline
|
多行模式:^ 行首 , $行尾
|
re.M
re.MULTILINE
|
IgnorePatternWhitespace
|
忽略表达式中的空白字符,如果要使用空白字符用转移,#可以用来做注释
|
re.X
re.VERBOSE
|
如何使用正则匹配ip地址
(?:25[0-5]|2[0-4]d|[01]?dd?.){3}(25[0-5]|2[0-4]d|[01]?dd?)
思路: 考虑最大上限,以及两位开头
python的正则表达式
python使用re模块提供了正则表达式
使用python正则匹配,应该先编译,在使用方法,提高效率
re.M多行模式
re.S单行
re.I忽略大小写
re.X忽略空白字符
使用 | 位或运算开启多种选项
使用方法 (编译) :
re.compile(pattern,flag=0) pattern(正则表达式字符串)(flag为选项)
编译:人工编写的正则表达式式电脑执行比较苦难,所以需要对其进行编译,编译后会得到一个正则表达式对象regex,从而提高效率,且re的其他调用达到也提速的效果
单次匹配
re.match(pattern,string,flag=0) 未编译
通过re模块对一个字符串由左至右匹配,找到第一个立即返回match对象
regex.match(string,pos=0,endpos=-1) 编译过
通过regex对象,对一个字符串由左至右匹配,找到第一个立即返回match对象
未编译使用match的缺点,用法单一,只能匹配第一个字符串开头的字符,若匹配项与被匹配的一个字符不符合,就会返回None
编译后使用match可以搭配索引锚定起始,来匹配指定位置
re匹配方法二:
search方法 re.search(pattern,string) 未编译 从头开始,由左至右匹配到第一个字符即返回一个match对象,只匹配一次 re.compile(pattern,pos=0,endpos=-1) regex.match(string) 以编译 从头开始,由左至右匹配到第一个字符即返回一个match对象,只匹配一次 re.fullmatch(pattern,string)全长匹配,整个字符串和正则表达式匹配,不满足则返回none
全部匹配
re.compile(pattern,pos=0,endpos=-1) 对正则进行编译,编译时可以指定多行或者单行模式 re.findall(pattern,string,flag=0) 未编译 regex.findall(string,pos=0,endpos=-1) 以编译 对整个字符串由左至右匹配,返回所有匹配项的列表 re.finditer(pattern,string,flag=0) 未编译 regex.finditer(string,pos=0,endpos=-1) 以编译
对整个字符串由左至右匹配,返回所有匹配项,返回迭代器,可以使用next()来对其进行惰性求值
每次迭代返回的是match对象
匹配对象替换
regex = re.compile('bwg') 全局替换 re.sub(pattern,replacement,string,count=0,flag=0) regex.sub(replacement,string,count=0) 使用pattern对字符串string'进行匹配,对匹配项使用repl替换 replacement可以是string,bytes,function re,sub(pattern,replacement,string,count=0,flags=0) 指定替换次数(count=?) regex.subn(replacement,string,count=0) 同sub返回一个元组
字符串分割
字符出啊你的分割函数,不能指定多个字符进行分割
使用re模块进行处理
re.split(pattern,string,maxsplit=0,flag=0)
re.split分割字符串
分组
使用小括号的pattern捕获的数据被放到到了组group中
matc search函数可以返回matc对象
示例:
log = '''183.60.212.153 - - [19/Feb/2013:10:23:29 +0800] "GET /o2o/media.html?menu=3 HTTP/1.1" 200 16691 "-" "Mozilla/5.0 (compatible; EasouSpider; +http://www.easou.com/search/spider.html)"''' flag=False lst=[] tmp ='' #先进性大的切割,拿到一小段 for word in log.split(): #对这些小段进行边界判断 if not flag and (word.startswith('[')or word.startswith('"')): if word.endswith(']') or word.endswith('"'): #如果找到它的出入口,直接将其加入到 业务列表中,并去掉两头的非法字符 lst.append(word.strip('[]"')) else: #若找不到它的出口,则打一个印记向后执行 tmp += word[1:] flag = True continue #利用标记进行下一步的处理 if flag: #若在此找到了它的边界 if word.endswith(']') or word.endswith('"'): #则将tmp的所有字符拼接起来,并追加入lst列表中,重置印记和tmp tmp += '' + word[:-1] lst.append(tmp) flag = False tmp =' ' else: #若还是没有找到,则继续添加这个字符,直到找到边界为止 tmp += ' '+word continue print(lst)