Regular Expression
文章目录
介绍正则表达式
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。换句话说,正则表达式就是记录文本规则的代码。正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。
正则表达式的工作机制
|
|
常用的元字符
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
元字符 | 描述 |
---|---|
. | 句号匹配任意单个字符除了换行符. |
[ ] | 字符种类. 匹配方括号内的任意字符. |
[^ ] | 否定的字符种类. 匹配除了方括号里的任意字符 |
* | 匹配>=0个重复的在*号之前的字符. |
|+|匹配>=1个重复的+号前的字符.
|?|标记?之前的字符为可选.|
|{n,m}|匹配num个中括号之前的字符 (n <= num <= m).|
|(xyz)|字符集, 匹配与 xyz 完全相等的字符串.|
|||或运算符,匹配符号前或后的字符.|
|\|转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ |
|
|^|从开始行开始匹配.|
|$|从末端开始匹配.|
锚点
在正则表达式中, 想要匹配指定开头或结尾的字符串就要使用到锚点. ^
指定开头, $
指定结尾.
^
用来检查匹配的字符串是否在所匹配字符串的开头. 例如, 在 abc
中使用表达式 ^a
会得到结果 a
. 但如果使用 ^b
将匹配不到任何结果. 因为在字符串 abc
中并不是以 b
开头. 例如, ^(T|t)he
匹配以 The
或 the
开头的字符串. 同理于 ^
号, $
号用来匹配字符是否是最后一个. 例如, (at\.)$
匹配以 at.
结尾的字符串.
重复
代码 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
反义 有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义:
代码 | 说明 |
---|---|
\W | 匹配任意不是字母,数字,下划线,汉字的字符 |
\S | 匹配任意不是空白符的字符 |
\D | 匹配任意非数字的字符 |
\B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
简写字符集
正则表达式提供一些常用的字符集简写. 如下:
简写 | 描述 |
---|---|
. | 除换行符外的所有字符 |
\w | 匹配所有字母数字, 等同于 [a-zA-Z0-9_] |
\W | 匹配所有非字母数字, 即符号, 等同于: [^\w] |
\d | 匹配数字: [0-9] |
\D | 匹配非数字: [^\d] |
\s | 匹配所有空格字符, 等同于: [\t\n\f\r\p{Z}] |
\S | 匹配所有非空格字符: [^\s] |
\f | 匹配一个换页符 |
\n | 匹配一个换行符 |
\r | 匹配一个回车符 |
\t | 匹配一个制表符 |
\v | 匹配一个垂直制表符 |
\p | 匹配 CR/LF (等同于 \r\n ),用来匹配 DOS 行终止符 |
回车"(carriage return)和"换行"(line feed) 的区别
回车每行后面加两个表示结束的字符。一个叫做"回车",告诉打字机把打印头定位在左边界;另一个叫做"换行",告诉打字机把纸向下移一行。从英文单词上也是能get 到意思的。
‘\n’ 10 换行(newline) ‘\r’ 13 回车(return)
回车 \r 本义是光标重新回到本行开头,r的英文return,控制字符可以写成CR,即Carriage Return 换行 \n 本义是光标往下一行(不一定到下一行行首),n的英文newline,控制字符可以写成LF,即Line Feed
不同操作系统下的含义:
\n: UNIX 系统行末结束符 \r\n: window 系统行末结束符 \r: MAC OS 系统行末结束符
软回车和硬回车
硬回车就是普通我们按回车产生的,它在换行的同时也起着段落分隔的作用。 软回车是用 Shift + Enter 产生的,它换行,但是并不换段,即前后两段文字在 Word 中属于同一“段”。在应用格式时你会体会到这一点。软回车能使前后两行的行间距大幅度缩小,因为它不是段落标记,要和法定的段落标记——硬回车区别出来。硬回车的html代码是 <p>..</p>
,段落的内容就夹在里面,而软回车的代码很精悍 <br>
。网页的文字如果复制到word中,则硬回车变为弯曲的箭头,软回车变为向下的箭头。
标志
标志也叫修饰语, 因为它可以用来修改表达式的搜索结果. 这些标志可以任意的组合使用, 它也是整个正则表达式的一部分.
标志 | 描述 |
---|---|
i | 忽略大小写. |
g | 全局搜索. |
m | 多行的: 锚点元字符 ^ $ 工作范围在每行的起始. |
修饰语 i
用于忽略大小写。例如, 表达式 /The/gi
表示在全局搜索 The
, 在后面的 i
将其条件修改为忽略大小写, 则变成搜索 the
和 The
, g
表示全局搜索.
修饰符 g
常用语执行一个全局搜索匹配, 即(不仅仅返回第一个匹配的, 而是返回全部). 例如, 表达式 /.(at)/g
表示搜索 任意字符(除了换行) + at
, 并返回全部结果.
多行修饰符 m
常用语执行一个多行匹配. 像之前介绍的 (^,$)
用于检查格式是否是在待检测字符串的开头或结尾. 但我们如果想要它在每行的开头和结尾生效, 我们需要用到多行修饰符 m
. 例如, 表达式 /at(.)?$/gm
表示在待检测字符串每行的末尾搜索 at
后跟一个或多个 .
的字符串, 并返回全部结果.
分枝条件 (定义了几种不同的匹配规则) 不幸的是,刚才那个表达式也能匹配(010)12345678或(022-87654321这样的“不正确”的格式。要解决这个问题,我们需要用到分枝条件。正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看例子:
0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。
(?0\d{2})?[- ]?\d{8}|0\d{2}[- ]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。
\d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。
分组(使用index 访问使用很广泛)
我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。
(\d{1,3}.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字,(\d{1,3}.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。
不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)。
常见的例子
除了使用[]表示或逻辑,()也是可以的。用法是(a|b)表示a或者b
- 匹配邮箱
|
|
步骤
- 任何一个以words开头的,一个或更多 \w+
- 紧接着是一个@符号 \w+@
- 接着有一个或者更多的words \w+@\w+
- 接着一个.标点 \w+@\w+.
- 接着一个com net 或 edu \w+@\w+.(com|net|edu)
手机号正则
|
|
单词边界
|
|
URL分组替换
|
|
正则表达式使用小括号用来分组,这个时候我们可以通过用 $1
来获取 group#1
的内容。 获取内容是为了 replace
正则表达式由两种基本字符组成:
- 原义字符
- 非打印字符
- 元字符 (* + ? $ ^ . | ( ) { } )
非打印字符包括换行符、回车符号, 分页符等等
字符类取反 [^]
范围类 [-]
预定义类 (这个是为了方便使用,在上面也被称为 简写类)
边界类
^
表示开头, $
表示结尾, \b
表示单词边界, \B
表示非单词边界
量词
正则表达式默认会匹配贪婪模式,什么是贪婪模式呢?如其名尽可能多的匹配。我们看个例子 与贪婪对应就是懒惰模式,懒惰对应的就是匹配的尽可能少的情况。如何开启懒惰模式? 在量词后面加?。继续上面的例子
|
|
邮箱正则表达式实例
分析邮件名称部分:
26个大小写英文字母表示为a-zA-Z
- 数字表示为0-9
- 下划线表示为_
- 中划线表示为-
- 由于名称是由若干个字母、数字、下划线和中划线组成,所以需要用到+表示多次出现
根据以上条件得出邮件名称表达式:[a-zA-Z0-9_-]+
分析域名部分:
分析邮件名称部分:
汉字在正则表示为 [\u4e00-\u9fa5]
字母和数字表示为 A-Za-z0-9
通过分析得出邮件名称部分表达式为 [A-Za-z0-9\u4e00-\u9fa5]+
C++ regex函数有3个:regex_match、 regex_search 、regex_replace
match是全文匹配,即要求整个字符串符合匹配规则。
|
|
search是搜索匹配,即搜索字符串中存在符合规则的子字符串。
|
|
regex_search和regex_match的主要区别是:regex_match是全词匹配,而regex_search是搜索其中匹配的字符串
regex_replace是替换正则表达式匹配内容的函数 replace是替换匹配,即可以将符合匹配规则的子字符串替换为其他字符串。
|
|
有时我们希望能够匹配的时候忽略大小写,这时候就要用到Regex的语法选项了。
|
|
针对python 的正则表达式的练习题
|
|
开始总结 python 版本的正则表达式
正则表达式 (Regular Expression) 又称 RegEx, 是用来匹配字符的一种工具. 在一大串字符中寻找你需要的内容. 它常被用在很多方面, 比如网页爬虫, 文稿整理, 数据筛选等等. 现在都是比较广泛学习,需要知道这里面都是有什么,等到用的时候,再好好琢磨,因为内容还是很多的呀。
要注意的是,正则表达式并不是一个程序,而是用于处理字符串的一种模式,如果你想用它来处理字符串,就必须使用支持正则表达式的工具,比如 Linux 中的 awk, sed, grep,或者编程语言 Perl, Python, Java 等等。
这个是一个引子, 关键字 in
表示字符串的匹配关系
|
|
如果想要使用更加强大的功能,那么使用 re
模块, 于是就是我们今天的主角- 正则匹配。 re
模块中提供了不少有用的函数, 比如
- compile 函数
- match 函数
- search 函数
- findall 函数
- finditer 函数
- split 函数
- sub 函数
- subn 函数
re 模块的一般使用的步骤
- 使用 compile 函数将正则表达式的字符串形式编译为一个 Pattern 对象
- 通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果(一个 Match 对象)
- 最后使用 Match 对象提供的属性和方法获得信息,根据需要进行其他的操作
compile 函数 compile 函数用于编译正则表达式,生成一个 Pattern 对象,它的一般使用形式如下:
|
|
其中,pattern 是一个字符串形式的正则表达式,flag 是一个可选参数,表示匹配模式,比如忽略大小写,多行模式等。
match 方法
match 方法用于查找字符串的头部(也可以指定起始位置),它是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。
search 方法 search 方法用于查找字符串的任何位置,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果
findall 方法 上面的 match 和 search 方法都是一次匹配,只要找到了一个匹配的结果就返回。然而,在大多数时候,我们需要搜索整个字符串,获得所有匹配的结果。
finditer 方法 finditer 方法的行为跟 findall 的行为类似,也是搜索整个字符串,获得所有匹配的结果。但它返回一个顺序访问每一个匹配结果(Match 对象)的迭代器。
split 方法 split 方法按照能够匹配的子串将字符串分割后返回列表
sub 方法 sub 方法用于替换。
匹配中文
在某些情况下,我们想匹配文本中的汉字,有一点需要注意的是,中文的 unicode 编码范围 主要在 [\u4e00-\u9fa5]
,这里说主要是因为这个范围并不完整,比如没有包括全角(中文)标点,不过,在大部分情况下,应该是够用的。
|
|
注意到,我们在正则表达式前面加上了两个前缀 ur
,其中 r
表示使用原始字符串,u
表示是 unicode 字符串。
执行结果:
|
|
总结
re 模块的一般使用步骤如下:
- 使用 compile 函数将正则表达式的字符串形式编译为一个 Pattern 对象;
- 通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果(一个 Match 对象);
- 最后使用 Match 对象提供的属性和方法获得信息,根据需要进行其他的操作;
Python 的正则匹配默认是贪婪匹配。
总结的小抄,出处
在爬虫中的实践
使用requests 得到内容之后,然后使用 re 进行解析。
|
|
linux 中常见的正则匹配实例
(1)How to find files recursively by file type and copy them to a directory while in ssh? 在一个文件中迭代查找所有某类的文件
|
|
正则匹配帮助文档
细说python正则表达式 ,写的非常全 Python 正则表达式 re 模块 也是比较好的博客
这个是实战,写的很容易理解 https://segmentfault.com/a/1190000013075245 https://blog.csdn.net/make164492212/article/details/51656638
python中的正则表达
字符串是编程中涉及最多的一种数据结构。正则表达式是一种从来匹配字符串的强有力的武器,它的设计思想是用一种描述性的语言来给字符串顶一个规则,凡是符合规则的字符串,就认为其匹配了,否则字符串不合法。
正则匹配 的准备知识
|
|
在python 中建议使用 r
前缀,这样就不用考虑转义问题。
|
|
- 判断是否匹配
|
|
- 切分字符串
|
|
- 分组
正则表达式有提取子串的功能。用 ()
表示提取的分组(group)
|
|
group extraction
The “group” feature of a regular expression allows you to pick out parts of the matching text. 主要用于提取想要的子串
|
|
- 贪婪匹配
正则表达式默认是贪婪匹配(尽可能多的匹配字符串)
|
|
由于\d+
默认采用的是贪婪匹配,直接把后面的0给全部匹配了,所以 0*
只能匹配空字符串。必须让 +d+
次用非贪婪匹配(尽可能少的匹配) 才能把后面的 0匹配出来。只需要加上一个?
就可以
|
|
对于贪婪模式产生的解释:因为有 + 和* 的出现
First the search finds the leftmost match for the pattern, and second it tries to use up as much of the string as possible – i.e. + and * go as far as possible (the + and * are said to be “greedy”).
- re.findall()
If you want to find all the substrings in a string, We can just use the findall method of the re module (No need to loop) findall returns all non-overlapping matches of pattern in string, as a list of strings. The string is scanned left-to-right, and matches are returned in the order in which they are found.
If one or more groups are present in the pattern, findall returns a list of groups. 如果有多个pattern,那么返回的 returns a list of groups
使用 |
表示 alternations,比如以下的例子:
|
|
大小写问题
|
|
使用参数,忽略大小写
findall() is probably the single most powerful function in the re module
re.search()
和re.findall()
区别:前者只是找到 first match for a pattern, findall 是找到了全部的match,returns them as a list of strings
|
|
findall with files (这个功能是比较实用的)
|
|
findall and groups
(使用的是上面涉及到的 ()
的用法)给个的简单的例子
|
|
- compile mode
python 中使用正则表达式的时候,re模块内部会做两件事情:(1)编译正则表达式 (2)用编译之后的表达式去匹配字符串
If you want to use the same regexp more than once in a script, it might be a good idea to use a regular expression object.
如果是多次使用,从效率的角度考虑,应该使用 compile mode
|
|
- re.search
|
|
- square brackets
Square brackets can be used to indicate a set of chars, so [abc] matches ‘a’ or ‘b’ or ‘c’. 这个是用来配置可选项的。
比如用以下的pattern 用来match 邮箱地址
|
|
文章作者 jijeng
上次更新 2020-06-28