正则表达式 Checklist
本文最后更新于 2023年7月28日 上午
正则表达式一直都是开发人员的必备技能,有人甚至提出在学习开发前先要熟练掌握正则表达式,可见其重要性。
这次利用实现 GA 数据分析的机会,整理了一个 Checklist 方便查阅(APP 上传的事件数据由于没有统一规定,内容千奇百怪,利用正则抽取其中关注的部分)。
根据 Free Code Camp 的教程来写的,原示例基于 JS 语言.
JS 中的正则
常用方法
- 基本 => 正则表达式的创建:JS 中正则模式使用 
//来定义, 因此不需要使用双引号。 - 方法 => test: 使用 Test 方法 
.test()用于检查字符串是否匹配模式,如果是返回true,regEx.test(someString)。 - 方法 => 
match: match 方法用于检测并返回匹配的字符串,比如"Hello, World!".match(/Hello/);返回["Hello"]。 - 注意 => match 和 test 的对象: test 是正则对象的方法, match 是字符串对象的方法.
 
常量匹配
常量匹配 => 大小写敏感:直接搜索常量,且默认匹配大小写,即 const testRegex = /Kevin/.
正则标志
- 标志 => 
i: 忽略大小写匹配, 使用i标志, 如:/someString/i - 标志 => 
g: 整串搜索匹配, 使用g标志(没有使用该标志则仅返回第一个匹配的子串)1
2
3let testStr = "Repeat, Repeat, Repeat";
let ourRegex = /Repeat/g;
testStr.match(ourRegex); // 返回 ["Repeat", "Repeat", "Repeat"] 
单字符匹配
- 单字符匹配 => 
.: 使用点通配符匹配一个任意字符
/hu./能匹配hug,huh,huu等 - 单字符匹配 => 字符集(character class) 
[]: 匹配集合中的某个字符, 比如/b[aiu]g/能够匹配bag,big,bug - 单字符匹配 => 字符集范围: 使用 
-指定字符集范围, 匹配范围内的任意一个字符(包含上下界的字符), 比如/[a-e]at/能够匹配aat,bat,cat,dat,eat - 单字符匹配 => 匹配范围内的字母或数字: 可以像这样定义 
[a-z0-9], 比如/[a-z0-9]/ig;用在Jenny8675309上可以匹配所有的单个字符, 如果使用 match 方法则返回的是该字符串的所有字符. - 单字符匹配 => 排除: 使用 
^可定义排除字符集, 比如/aeiou/ig匹配单个非元音字符(但这样写的话所有.,!这些非字母字符也会被匹配到, 甚至是空格, 因只排除了元音字母)1
2
3let quoteSample = "3 blind mice.";
let myRegex = /[^aeiou0-9]/ig; // 匹配排除元音和数字的其他所有字符, 且整串搜索忽略大小写
let result = quoteSample.match(myRegex); // 返回所有 9 个匹配的字符: 空格 b l n d 空格 m c . - 单字符匹配 => 
\w: 匹配任意字母数字或下划线, 相当于[A-Za-z0-9_]的简化写法/\w/g用在are you上返回["a", "r", "e", "y", "o", "u"]
 - 单字符匹配 => 
\W: 匹配任意非字母数字和下划线, 相当于[^A-Za-z0-9_]/\W/用在42%上返回["%"]
 - 单字符匹配 => 
\d: 匹配数字, 相当于[0-9] - 单字符匹配 => 
\D: 匹配非数字, 相当于[^0-9] - 单字符匹配 => 
\s: 匹配空白符, 包括空格, 换行, tab, form feed 等, 相当于[\r\n\t\f\v] - 单字符匹配 => 
\S: 匹配非空白符, 相当于[^\r\t\f\n\v] 
多字符匹配
- 多字符匹配 => 
+: 匹配出现一次或多次, 比如/a+/g, 用在abc上返回["a"], 用在aaabc上返回["aaa"], 用在abab上返回["a", "a"] - 多字符匹配 => 
*: 匹配出现 0 次或多次, 比如/go*/, 用在"gooooooooal!"上返回["goooooooo"], 用在gut feeling上返回["g"](u匹配 0 次或多次), 用在over the moon上返回 null - 多字符匹配 => 贪心匹配和懒匹配: 
- 利用 
*可以进行贪心匹配(最长匹配),/t[a-z]*i/用在"titanic"返回["titani"] - 利用 
?可以进行懒匹配(最短匹配),/t[a-z]*?i/用在"titanic"返回["ti"] - 利用 
?还可以表达”可以匹配, 也可以不匹配”, 比如/favou?rite/可以匹配favorite和favourite 
 - 利用 
 - 多字符匹配 => 
^: 匹配字符串开头, 比如/^Ricky/- 用在 
"Ricky is first and can be found."返回["Ricky"] - 用在 
"You can't find Ricky now."返回null 
 - 用在 
 - 多字符匹配 => 
$: 匹配字符串结尾, 比如/story$/- 用在 
"This is a never ending story"返回["story"] - 用在 
"Sometimes a story will have to end"返回null 
 - 用在 
 - 多字符匹配 => 
\w+: 匹配任意一个或多个字母数字或下划线, 比如/\w+/- 用在 
"42"返回["42"] - 用在 
"important_var"返回["important_var"] - 用在 
"are you"返回["are", "you"] 
 - 用在 
 - 多字符匹配 => 
\W+: 匹配连续多个非字母数字下划线字符 - 多字符匹配 => 
\d+: 匹配连续多个数字 - 多字符匹配 => 
\D+: 匹配连续多个非数字字符 
特殊操作
或操作符
|: 比如/^[a-z][a-z]+\d*$|^[a-z]\d\d+$/i中就是或操作符, 操作符两侧优先按左侧匹配, 未匹配则再看右侧出现频次限定: 比如
/a{3,5}h/可以匹配aaaah, 但不能匹配aah{2,}(仅下限){3,5}(上下限){3}(固定次数)
正则表达式中允许出现括号
()以包括多个模式, 比如/^[a-z]([0-9]{2,}|[a-z]+\d*)$/i;中限定末尾匹配的相关表达.Lookahead: 前瞻, 即仅判断是否满足指定正则, 但不进行后续匹配, 当想在一个字符串中使用多种正则查找时非常有用.
- positive: 
(?=...)其中...是具体正则, positive 会根据指定的正则确认匹配是否存在, 但不匹配该正则. - negative: 
(?!...)其中...是具体正则, negative 会根据指定的正则确认匹配是否不存在, 但不匹配该正则. 
例如给一个字符串
"qu":- 如果使用 
/q(?=u)/进行匹配则返回q(匹配到存在的位置, 但不进行后面的匹配) - 如果使用 
/q(?!t)/, 也仍会返回q(匹配到不存在的位置, 但不进行后面的匹配) 
- positive: 
 使用
|配合()可以匹配一组正则: 比如/P(engu|umpk)in/可以匹配Penguin和PumpkinReuse Patterns Using Capture Groups: 使用括号包含的
(\w+) \1, 即利用 capture group, 通过编号在后面进行引用.Use Capture Groups to Search and Replace: 使用 replace 方法, 利用 capture group 捕捉到的字符串进行替换, 或者是将匹配到的内容替换为新的字符串.
Remove Whitespace from Start and End: 这个练习中识别开头和结尾的连续空白, 并用 replace 替换为空, 即可去掉所有空白.
Python
compile方法创建正则表达式对象匹配 import 语句:
1
2
3
4
5
6
7
8[
('#import ', '<', 'Foundation/', 'Foundation.h', '>'),
('#import ', '<', 'sqlitemanager/', 'FMDatabase.h', '>'),
('#import ', '<', 'sqlitemanager/', 'FMResultSet.h', '>'),
('#import ', '<', 'sqlitemanager/', 'FMDatabaseAdditions.h', '>'),
('#import ', '<', 'sqlitemanager/', 'FMDatabaseQueue.h', '>'),
('#import ', '<', 'sqlitemanager/', 'FMDatabasePool.h', '>')
]可以使用这个:
1
2
3import_regex = r'^(#import\s)(<)(\w+\/)*(\w+\.h)(>)(\s*)$'
match_import_regex = re.compile(import_regex, re.IGNORECASE | re.MULTILINE)
result = match_import_regex.sub(r'\1"\4"\6', content)抽取关注的内容, 如:
1
'["ver": "1.2.34.56", "id": " xxxxx-xxxxx-xxxxx-xxxxx-xxxx-- --2021-10-08 02:16:05 +0000,\\n sysV:11.6.0 Arm64"]'1
2
3
4ver_regex = r'("ver":\s*)"((\d+\.)*\d+)"'
id_regex = r'([A-Z0-9]{5}-){4}([A-Z0-9]{4})'
event_date_regex = r'(\d{4}(-\d{2}){2}) ((\d{2}:*)*) \+\d{4}'
sys_info_regex = r'sysV:(\d+.*?)\s(\w+),'