正则表达式 是一种文本模式,一种文本的查找标准,不仅仅是在编程中可以进行一些字符串的处理,当正确掌握了正则表达式的使用规则时,在日常的文本编辑的过程中,也可以帮助我们非常便利,快捷的进行查找和替换。
所以学习正则表达式,除了通过编写代码 demo 的形式,也可以尝试直接在一些常用的编辑器(例如 Visual Studio Code 等)中,打开
Ctrl+F
查询面板,其实就可以进行简单的正则表达式匹配的编写了,编辑器的查找功能还会实时将匹配的部分高亮,可以快速协助调试和测试正则表达式。而正则表达式对于大部分流行的编程语言来说基本上都是通用的,因此,后续只需要学习相应的编程语言中,例如
Python
的
re
模块,
JavaScript
的
/(reg)/
表达式语法等具体编程语言中的使用即可,本质上都是相同的,掌握了常用的方法就可以在各种场景中使用了。
1. 元字符
元字符通常表示一类字符的集合,用于匹配符合该规则集合内的所有字符,比如在编写程序的过程中,在大多数编程语言的字符串中都通用的元字符 '\t'
,'\n'
,分别表示制表符和换行符。
在正则表达式中,元字符通常用 \字母
表示,例如 \d
和 \D
,通常都有对应的大小写表达式,表示互补的两个字符集合,常用的字符集合如下:
-
\d
:匹配数字,即[0-9]
,\D
表示补集,即数字以外的所有字符,例如JavaScript
的字符串验证:// 至少包含数字 const password_pattern = /\d/; // true,匹配结果为 ['1', '2', '3', '4'] console.log(password_pattern.test('abcd+1234')); // false console.log(password_pattern.test('abcd');
-
\s
:匹配空白字符,同理\S
即所有非空白字符// 检查空白字符 const check_blank_in_username = /\s/; // false console.log(check_blank_in_username.test('Annie')); // true, invalid username console.log(password_pattern.test('Jason Lin');
-
\w
:所有字母,下划线和数字,同理\W
表示补集// 检查变量名称可用字符 const check_var_name = /\w/; // true console.log(check_var_name.test('ant_design_table')); // false, invalid variable name console.log(password_pattern.test('image&text_object');
另外,.
将匹配除 \n
之外的所有字符,即 \n
的补集:
// 检查是否包含多行
const test_line = /./;
// true, a single line
console.log(test_line.test('This is a single line without any enter!'));
// false, multiple lines found
console.log(test_line.test('This is the first paragraph\nHere comes the second!!');
而如果需要匹配用于元字符中涉及到的功能字符 .
和 \
的话,就需要进行转义:\.
,\\
进行匹配。
对于元字符来说,本质上都是表示一个字符集合,对于匹配,其实就是一个包含和不包含的关系,因此,也可以通过在 []
中指定字符集合来进行匹配:
// 匹配 0 或 1
const p1 = /[01]/
// | 表示或,与上同义
const p1 = /[0|1]/
// 数字,'-' 表示范围
const numbers = /[0-9]/ // 0-9 的数字,即 \d
const no_numbers = /[^0-9]/ // 所有非数字,即 \D
// 字母
const low_case_letters = /[a-z]/ // 所有小写字母
const up_case_letters = /[A-Z]/ // 所有大写字母
// 也可以结合使用,即字符串应包含数字,大写字母以及下划线,集合中先后顺序无关
const password = /[0-9_A-Z]/ // _0-9A-Z, 0-9A-Z_ 均可,加上小写字母表示 \w
注意:在
[]
中字符没有先后以及连接顺序,仅表示集合,即里面每个字符都表示单个字符,例如:[jhserg]
表示匹配'j','h','s','e','r','g'
这 7 个字符,同理[^jhserg]
表示匹配这几个字符之外的全部,即[^]
表示目标集合的补集。如果希望不包含和包含同时使用的话,可以结合前文中的各个元字符以及其互补集合进行组合使用。
2. 量词,行首行末匹配
2.1 量词
而在对某个字符串进行匹配的时候,往往还需要指定需要匹配的字符的数量,从而确定检测的输入中是否包含指定要求的格式:
-
+
表示匹配一个或者以上指定模板,即至少包含一个符合指定格式要求的字符或者子串,例如:// 至少包含 1 个数字 const pattern = /\d+/
-
*
:包含多个或者不包含指定格式的子串 -
?
:可以理解为一种询问,即:“有没有包含指定的子串?”,所以,此元字符表示有或者没有,即包含一个或者不包含,例如:// 允许携带后缀或者不携带,可以用于格式兼容 // 匹配 tomato 和 tomatos const format = /tomatos?/ // 匹配 ver_3_1_n n 为任意数字,即匹配 3_1` const pattern_suffix = /ver_3_1(_\d)?/ // 通过 () 表示 ? 的目标为括号中的整体
-
{m,n}
:表示包含连续的 [ m , n ] [m,n] [m,n] 个字符,其中 m ≤ n m\le n m≤n,或者 n n n 可以为空,这是量词的通用模板,以上三个量词均可以用此语法表示:const plus = /{1,}/ // + const star = /{0,}/ // * const ques = /{0,1}/ // ?
另外,也可以指定确定的字符数量,例如标准格式化的日期的每个位置的长度都是固定的,比如
'2023-03-28'
,可以通过下面的正则表达式匹配日期:const date_pattern = /\d{4}-\d{2}-\d{2}/
到这里,相信可以自己尝试写一下匹配包含时分秒的一个完整的
datetime
日期字符串格式,或者是日志输出以及命令的格式化输出,从中提取出需要的内容了
2.2 行首行末
对于一些格式化输出,例如日志或者是工具输出,需要匹配指定前缀或者指定后缀,可以通过 ^
和 $
// 以 dis 和 un 开头
const find_negative_word = /^(dis|un)/
// disable => true
// under => true
// dunk => false
// 匹配 ERROR 日志
const find_error_log = /^(\[ERROR\])/
// [ERROR] List out of bound => true
// 匹配 {} 包裹的行,中间包含字母数字下划线和空白字符
const find_end_with_braces = /^\{[\s\w]*\}$/ // 需要转义 \{,\}