在工作中,为了提高工作效率,我们必须要学会使用Linux下的各种工具,它们强大而高效。正则表达式则是这些高效的工具之一,无论是文本处理命令grep、sed、awk中使用正则表达式,还是在代码编译器VS Code中使用正则表达式,都可以快速地帮助我们进行文本的查找或者替换,提高编写代码或者解决问题的工作效率,减少时间的浪费。
1. 什么是正则表达式
如果要用grep
查找一个模式,如何表示这个模式,这一类字符串,而不是一个特定的字符串呢?要表示一个模式至少应该包含以下信息:
-
数量限定符(Quantifier): 例如邮件地址的每一部分可以有一个或多个x字符,IP地址的每一部分可以有1-3个y字符
-
各种字符类以及普通字符之间的位置关系:例如邮件地址分三部分,用普通字符
@
和.
隔开,IP地址分四部分,用.
隔开,每一部分都可以用字符类和数量限定符描述。为了表示位置关系,还有位置限定符(Anchor)的概念,将在下面介绍。
规定一些特殊语法表示字符类、数量限定符和位置关系,然后用这些特殊语法和普通字符一起表示一个模式,这就是正则表达式(Regular Expression)。例如email地址的正则表达式可以写成[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+
,IP地址的正则表达式可以写成[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
。
2. 基本语法
2.1 字符类
字符 | 含义 | 举例 |
---|---|---|
. | 匹配任意一个字符 | abc. 可以匹配abcd 、abc9 等 |
\d | 数字匹配符 | 可以匹配到数字0-9 |
\D | 非数字匹配符,\d的反义 | 可以匹配任意非0-9的数字 |
\w | 字母数字下划线匹配符 | 可以匹配任意字母a-z和A-Z、数字0-9和下划线- |
\W | 非字母数字下划线匹配符,\w的反义 | 可以匹配任意非字母a-z和A-Z、数字0-9和下划线- |
\s | 空白符匹配符 | 可以匹配任意空白符,包括回车、换行、制表符 |
\S | 非空白符匹配符 | 可以匹配任意非空白符,除了回车、换行、制表符之外的 |
\r | 匹配回车符 | |
\n | 匹配换行符 | |
\f | 匹配换页符 | |
\t | 匹配制表符 | |
\v | 匹配垂直制表符 | |
[] | 匹配括号中的任意一个字符 | [abc]d 可以匹配ad 、bd 或cd,\w可以用[0-9a-zA-Z_]表示 |
- | 在[] 括号内表示字符范围 | [0-9a-fA-F] 可以匹配一位十六进制数字 |
^ | 位于[] 括号内的开头,匹配除括号中的字符之外的任意一个字符 | [^xy] 匹配除xy 之外的任一字符,因此[^xy]1 可以匹配a1 、b1 但不匹配x1 、y1 |
[[:xxx:]] | grep 工具预定义的一些命名字符类 | [[:alpha:]] 匹配一个字母,[[:digit:]] 匹配一个数字 |
2.2 数量限定符
字符 | 含义 | 举例 |
---|---|---|
? | 紧跟在它前面的单元应匹配0次或1次 | [0-9]?\.[0-9] 匹配0.0 、2.3 、.5 等,由于. 在正则表达式中是一个特殊字符,所以需要用\ 转义一下,取字面值 |
+ | 紧跟在它前面的单元应匹配 >=1 次 | [a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+ 匹配email地址 |
* | 紧跟在它前面的单元应匹配 >= 0 次 | [0-9][0-9]* 匹配至少一位数字,等价于[0-9]+ ,[a-zA-Z_]+[a-zA-Z_0-9]* 匹配C语言的标识符 |
{N} | 紧跟在它前面的单元应精确匹配N次 | [1-9][0-9]{2} 匹配从100 到999 的整数 |
{N,} | 紧跟在它前面的单元应匹配至少N 次 | [1-9][0-9]{2,} 匹配三位以上(含三位)的整数,{1,}相当于+号,{0,}相当于*号 |
{,M} | 紧跟在它前面的单元应匹配最多M 次 | [0-9]{,1} 相当于[0-9]? |
{N,M} | 紧跟在它前面的单元应匹配至少N 次,最多M 次 | [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} 匹配IP地址,{0,1}相当于?号 |
2.3 位置限定符
字符 | 含义 | 举例 |
---|---|---|
^ | 匹配行首的位置 | ^Content 匹配位于一行开头的Content |
$ | 匹配行末的位置 | ;$ 匹配位于一行结尾的; 号,^$ 匹配空行 |
\< | 匹配单词开头的位置 | \<th 匹配... this ,但不匹配ethernet 、tenth |
\> | 匹配单词结尾的位置 | p\> 匹配leap ... ,但不匹配parent 、sleepy |
\b | 匹配单词开头或结尾的位置 | \bat\b 匹配... at ... ,但不匹配cat 、atexit 、batch |
\B | 匹配非单词开头和结尾的位置 | \Bat\B 匹配battery ,但不匹配... attend 、hat ... |
2.4 其它特殊字符
字符 | 含义 | 举例 |
---|---|---|
\ | 转义字符,普通字符转义为特殊字符,特殊字符转义为普通字符 | 普通字符< 写成\< 表示单词开头的位置,特殊字符. 写成\. 以及\ 写成\\ 就当作普通字符来匹配 |
() | 将正则表达式的一部分括起来组成一个单元,可以对整个单元使用数量限定符 | ([0-9]{1,3}\.){3}[0-9]{1,3} 匹配IP地址 |
| | 连接两个子表达式,表示或的关系 | n(o|either) 匹配no 或neither |
3. 实战演练
(1)匹配邮箱:[0-9a-zA-Z-_.]+@[0-9a-zA-Z-_.]+\.[0-9a-zA-Z-_.]+
(2)匹配IP地址:([0-9]{1,3}\.){3}[0-9]{1,3}
(3)匹配时间和日期: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}