一、概述
正则表达式(Regular Expression)是计算机科学的一个概念,它使用单个字符串来描述、匹配一系列符合某个句法规则的字符串,在现在很多文本编辑器或IDE开发工具里,正则表达式通常被用来查找或替换某个模式的文本。因此,灵活运用正则表达式,对某些问题可以另辟蹊径地快速解决。
二、语法
正则表达式的语法非常简洁,学习起来也很好入门,所以重点是要如何能够灵活运用,能够快速解决一些问题。因此,这篇文章的重心主要放在实践,对于一些语法细节,随便去网上看看教程就能掌握。大部分教程的语法定义不一样,我就按照自己的理解,把语法部分分为代词、量词、元字符三部分。
1. 代词
代词是在匹配字符串时,可以代指某类或某个字符的表达式词。普通字符可以直接用来匹配,包括大写和小写字母、数字、标点符号等打印字符,以及换行符(\n
)、回车符(\r
)、制表符(\t
)等非打印字符。除此之外,常用的代词有:
字符 | 功能 |
. |
匹配除 \r\n 之外的任何单个字符 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等,等价于 [\f\n\r\t\v] |
\S |
匹配任何非空白字符,等价于 [^\f\n\r\t\v] |
\d |
匹配一个数字字符,等价于 [0-9] |
\D |
匹配一个非数字字符,等价于 [^0-9] |
\w |
匹配包括下划线的任何单词字符,等价于 [A-Za-z0-9_] |
\W |
匹配任何非单词字符,等价于 [^A-Za-z0-9_] |
如果需要匹配的字符与正则表达式的关键字符一样,在前面使用反斜杠(
\
)来转义,例如匹配中括号需要用\[\]
。
2. 量词
量词用于代词的后面,用来表示前面代词重复出现的个数,代词后面不加量词则代表出现一次且仅出现一次,常用的量词有:
字符 | 功能 |
? |
表示前面的字符最多只可以出现一次(0次或1次) |
* |
表示前面的字符可以不出现,或出现一次或多次(0次、1次或多次) |
+ |
表示前面的字符必须至少出现一次(1次或多次) |
{n} |
表示前面的字符出现 n 次(n为非负整数) |
{n,} |
表示前面的字符至少出现 n 次(n为非负整数) |
{n,m} |
表示前面的字符至少出现 n 次,至多出现 m 次(m和n为非负整数,n小于等于m) |
3. 元字符
元字符是正则表达式自带的特定功能的字符,具有定位或指定匹配范围等功能。常用的元字符有:
字符 | 功能 |
^ |
匹配输入字符串的开始位置,可以是行首 |
$ |
匹配输入字符串的结束位置,可以是行尾 |
x|y |
匹配 x 或 y ,没有包围在括号里的,范围是整个正则表达式 |
[xyz] |
匹配所包含的任意一个字符 |
[^xyz] |
匹配未列出的任意字符 |
[a-z] |
匹配指定范围内的任意字符,例如 [0-9],[A-Z] 等 |
(pattern) |
匹配 pattern 并获取这一匹配的子字符串,可以使用 $0...$9 可以获取匹配的字符串 |
三、实践
1. 区分贪婪模式和非贪婪模式
*
和 +
量词都是贪婪的,会尽可能多的匹配文字,在它们后面加上一个 ?
就可以实现非贪婪匹配。例如匹配下面带双引号的字符串:
Regular expression are used by string searching algorithms for "find" or "find and replace" operations on strings, or for input validation.
使用 ".*"
匹配的结果是 "find" or "find and replace"
。
使用 ".*?"
匹配的结果是 "find"
和 "find and replace"
。
2. 删除多余空行
使用替换换行符来删除多余空行,将出现大于1次的换行符替换成1个换行符就能实现删除多余空行。例如将下面文字中的多余空行删除:
You say that you love rain,but you open your umbrella when it rains You say that you love the sun,but you find a shadow spot when the sun shines You say that you love the wind,but you close your windows when wind blows This is why I am afraid,you say that you love me too
操作如下:
3. 简单获取文本中的URL
有些时候我们需要从一堆文字中找到自己想要的信息,例如爬虫程序,此时可以使用正则来匹配信息,例如从下面一堆文字中找出有效的接口URL全路径:
DealerAll 1.100s Method arguments: "https://demo.mljr.com/crmappApi/dealer/all", "0", "1", "", "", "", "", "", "", "", "", "", "", "" DealerGetDeptCondition 0.058s Method arguments: "https://demo.mljr.com/crmappApi/dealer/getDeptCondition", "0", "" DealerListConditionMarkets 0.049s Method arguments: "https://demo.mljr.com/crmappApi/dealer/list/condition/markets", "0" DealerPrivate 0.080s Method arguments: "https://demo.mljr.com/crmappApi/dealer/private", "0", "1", "", "", "", "", "", "loanOrderOneMonth", "desc", "", "", "", "" StaffGetStaffInfo 0.111s Method arguments: "https://demo.mljr.com/crmappApi/staff/getStaffInfo", "0"
首先分析目标文字特征,只有 https://
开头的双引号内的字符串才是接口URL,所以匹配步骤如下:
- 输入
"https://.*?"
来匹配URL,注意这里需要使用非贪婪模式 - 添加
.*"(https://.*?)".*
,使用括号来定位URL信息,前后使用.*
来匹配URL到行首和行尾的内容 - 替换内容为
$1
,取第1次匹配到的内容,这里只有一组括号,所以第1次匹配的内容就是URL
4. 替换HTML标签内容
如果需要匹配已知开头结尾的字符串,可以使用正则表达式来获取,使用正则表达式的技巧并不是语法的难度,关键是要分析出目标字符串的规律与特性,巧用查找与替换的技巧可以事半功倍,例如将下面HTML文件中的一级标题内容前面添加 Title
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Hello world</title> </head> <body> <h1>AiJiangnan</h1> <h1>AiJiangnan</h1> </body> </html>
所有的一级标题都是
...
只需将它们匹配到并替换即可,步骤如下:
- 输入
匹配所有的一级标题,注意使用非贪婪模式,并且标签内容使用括号定位(.*?)
- 替换内容为
,使用Title $1
$1
取原有标签内容,在前面添加Title
完成替换
5. 巧用多行编辑完成重复操作
现在大多数编辑器都支持多行编辑,使用正则表达式来查找出所有需要编辑的位置,然后使用多行编辑功能来完成大部分重复的工作,这能大大提高编码的效率。例如我们在Java代码中定义了一个视图实体类,要添加Swagger注解来生成接口文档,可以从每个字段的注释中获取字段描述来编辑,示例步骤如下:
- 分析并查找目标字符串,这里可以查找
private
- 查找完成后,使用多行编辑
- 添加注解代码后复制注释完成编写