第14期 - 看演唱会

封面图来源于贵阳场JJ演唱会现场,机缘巧合抢到了家门口的票,也算是圆梦了。

技术笔记-正则表达式相关

非贪婪模式-更精确地提取所需内容,避免过度匹配,提高性能
贪婪模式:会尽可能多地匹配字符

基础

创建一个正则表达式

const regex = /pattern/flags;

pattern 是你要匹配的模式。
flags 是正则表达式的标志(可选),例如 g(全局匹配),i(忽略大小写),m(多行匹配)等。

动态创建正则表达式

const regex = new RegExp('pattern', 'flags');

🌰

const regex = new RegExp('\\d+', 'g'); // 注意要对反斜杠进行转义

表达式的字符类型

正则表达式有以下不同类型的字符:

元字符(Metacharacters)
量词(Quantifier)
组和范围(Groups and Ranges)
转义字符或字符类(Escape Characters or Character Classes)

元字符

【 . 】匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。
【\d】匹配一个数字字符。等价于[0-9]。
【\w】匹配一个单词字符(字母、数字或下划线)等价于“[A-Za-z0-9_]”。
【\s】匹配一个空白字符(空格、制表符等)包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
【^】匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置
【$】匹配输入的结尾(匹配输入字符串的结束位置) 如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。

量词

*】匹配前一个元素0次或多次。例如,zo*能匹配“z”以及“zoo”。*等价于{0,}。
【+】匹配前一个元素1次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
注: 【*】量词只作用于紧跟在它前面的那个元素
【?】匹配前一个元素0次或1次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。
【{n}】匹配前一个元素恰好n次。n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
【{n,}】匹配前一个元素至少n次。n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
【{n,m}】匹配前一个元素至少n次但不超过m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。

标志

g:全局搜索。
i:不区分大小写搜索。
m:多行搜索。

正则方法函数

test() 方法用于测试一个字符串是否匹配一个正则表达式。如果匹配返回 true,否则返回 false。

const regex = /\d+/;
const str = "There are 123 apples";
console.log(regex.test(str)); // 输出: true

exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null。

const regex = /\d+/;
const str = "There are 123 apples";
const result = regex.exec(str);
console.log(result); // 输出: ["123"]

match() 方法在一个字符串中检索匹配的字符串。返回一个数组或 null。

replace() 方法在字符串中替换与正则表达式匹配的子串。

const str = "There are 123 apples";
const result = str.replace(/\d+/, 'many');
console.log(result); // 输出: "There are many apples"

使用的例子

匹配Email地址

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
const email = 'example@example.com';
console.log(emailRegex.test(email)); // 输出: true

匹配日期格式(yyyy-mm-dd)

const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
const date = '2024-07-03';
console.log(dateRegex.test(date)); // 输出: true

匹配URL

const urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
const url = 'https://www.example.com/path/to/page';
console.log(urlRegex.test(url)); // 输出: true

进阶用法

exec 示例

const str = "foooood boo oooo";
const regex = /o{2,}/g;
let result;

while ((result = regex.exec(str)) !== null) {
  console.log(result); // 输出: ["ooooo"], ["oo"], ["oooo"]
}

有效地逐个获取所有匹配结果,并在每次循环中处理这些结果。这种方式特别适合处理需要遍历和处理所有匹配结果的情况

用法更详细的解释:
在 while 循环中,result = regex.exec(str) 这个表达式有两个作用:
1.调用 exec 方法:
每次循环开始时,exec 方法会从上次匹配的位置继续向后搜索匹配。
如果找到了匹配,exec 返回一个数组,其中包含匹配的结果;如果没有找到匹配,返回 null。
2.循环终止条件:
while 循环的终止条件是 (result = regex.exec(str)) !== null。
这个条件的含义是:只要 exec 方法返回的结果不是 null(即找到了匹配),则继续执行循环体;一旦 exec 返回 null(即没有找到更多匹配),则退出循环。

match 示例

const str = "foooood boo oooo";

// 非全局模式
let result = str.match(/o{2,}/);
console.log(result); // 输出: ["ooooo"]

// 全局模式
result = str.match(/o{2,}/g);
console.log(result); // 输出: ["ooooo", "oo", "oooo"]

match 更适合简单的匹配操作,尤其是在不需要逐个处理匹配结果时。
exec 更灵活,适合需要逐个处理匹配结果的场景,特别是当需要访问捕获组或在复杂匹配逻辑中使用时。